単純なロケーション マップがあり、ユーザーがリモート ファイルにリストされているロケーションに近づいたときにアプリをビープ音で鳴らしたい
リストされた場所は、locations.txt という名前のサーバーにあります
ユーザーが場所から 300 m 以内にいるかどうかを確認するために、location.txt を 1 分ごとに確認するにはどうすればよいですか??
この質問に対する標準的な答えは、場所認識ガイドで説明されている形状ベースの領域です。一般に、領域の数が限られている場合は、形状ベースの領域が適しています。ただし、多くのリージョンが必要な場合は、「自分で作成」する必要がある場合があります。
位置情報サービスをオンにして、現在地を監視します。Location Awareness プログラミング ガイドを参照してください。標準の位置情報サービスを使用する場合desiredAccuracy
は、必要な機能を実現するために、a をできるだけ低く設定してください (例: kCLLocationAccuracyHundredMeters
)。
最初の を正常に受信しdidUpdateLocations
たら、本当に毎分確認したい場合は、その時点でタイマーを作成できます。そのタイマーの目的がユーザーの位置を確認することだけである場合、タイマーは実際には必要なく、didUpdateLocations
.
監視する場所の配列を反復処理して (私はそれらをCLLocation
オブジェクトに変換します)、単純に を使用できますdistanceFromLocation
。
ただし、いくつかの観察事項があります。
locations.txt
ユーザーがその場所から 300 m 以内にいるかどうかを毎分チェックすることをお勧めします。あなたがその解決策を提案した理由は 2 つあります。
サーバーlocations.txt
変わった?これが解決しようとしている問題である場合、より良い解決策はプッシュ通知(別名「リモート通知」) であり、クライアントが最新の情報にアクセスできるようにする必要があります。ファイルを絶えず再取得するプロセスは、非常にコストがかかります (帯域幅、バッテリー、計算の観点から)。また
ユーザーは移動しましたか?ユーザーが移動したかどうかが心配な場合、適切な解決策は、毎分チェックするのではなく、 [ CLLocationManagerDelegate
] インスタンス メソッドdidUpdateLocations
が呼び出されるのを待つことです。冗長なチェックが多すぎるのを避けたい場合は、最後のリクエストが 1 分以内に行われたかどうかを常に追跡し、1 分以上前に行われた場合にのみ再度チェックすることができます。しかし、それは、必要かどうかを毎分チェックすることとは大きく異なります。
テキストファイルの使用を提案しました。サーバーからデータを取得するための優れたメカニズムである JSON ファイル (または XML ファイル) の使用を検討することもできます。
たとえば、JSON 形式のテキスト ファイルがある場合、別の 1 行のコードで結果を解析できます ( JSONObjectWithData
)。説明のために、JSON ファイルがどのように見えるかを示しましょう (ここで、角括弧は配列を示し、中括弧は辞書を示します。したがって、これは辞書の配列です)。
[
{
"name" : "Battery Park",
"latitude" : 40.702,
"longitude" : -74.015
},
{
"name" : "Grand Central Station",
"latitude" : 40.753,
"longitude" : -73.977
}
]
その後、アプリは次の 2 行で非常に簡単に結果を取得できます。
NSData *locationsData = [NSData dataWithContentsOfURL:url];
NSArray *locationsArray = [NSJSONSerialization JSONObjectWithData:locationsData options:0 error:&error];
したがって、位置情報サービスを開始する必要があります。
if (nil == self.locationManager)
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyKilometer;
// Set a movement threshold for new events.
self.locationManager.distanceFilter = 500;
[self.locationManager startUpdatingLocation];
次に、現在の場所を確認するためのルーチンがあります。
- (void)checkLocation
{
NSURL *url = [NSURL URLWithString:kLocationsUrlString];
NSData *locationsData = [NSData dataWithContentsOfURL:url];
NSAssert(locationsData, @"failure to download data"); // replace this with graceful error handling
NSError *error;
NSArray *locationsArray = [NSJSONSerialization JSONObjectWithData:locationsData
options:0
error:&error];
NSAssert(locationsArray, @"failure to parse JSON"); // replace with with graceful error handling
for (NSDictionary *locationEntry in locationsArray)
{
NSNumber *longitude = locationEntry[@"longitude"];
NSNumber *latitude = locationEntry[@"latitude"];
NSString *locationName = locationEntry[@"name"];
CLLocation *location = [[CLLocation alloc] initWithLatitude:[latitude doubleValue]
longitude:[longitude doubleValue]];
NSAssert(location, @"failure to create location");
CLLocationDistance distance = [location distanceFromLocation:self.locationManager.location];
if (distance <= 300)
{
NSLog(@"You are within 300 meters (actually %.0f meters) of %@", distance, locationName);
}
else
{
NSLog(@"You are not within 300 meters (actually %.0f meters) of %@", distance, locationName);
}
}
}
これは、ユーザーの場所が変更されたときに呼び出されます。
// this is used in iOS 6 and later
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
[self checkLocation];
}
// this is used in iOS 5 and earlier
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
if ([[[UIDevice currentDevice] systemVersion] floatValue] < 6.0)
[self checkLocation];
}
実装は、GitHub のこのテスト プロジェクトのようになります。これは最低限の実装ですが、手元にあるツール、つまりlocations.json
ファイルを取得し、それをデバイスによって取得された場所と比較するツールのアイデアを提供します。