web-dev-qa-db-ja.com

iOSジオフェンシングで複数(20以上)の場所を追跡する

IOSアプリケーションは、ジオフェンシングを使用して、事前定義された近くの場所についてユーザーに通知します。アプリケーションは特定の場所を見逃すことは許可されていますが(ユーザーは近くの場所に関する通知を受け取っていません)、見逃し率を低く保つことが望ましいです。

これを実装する1つの方法は、startMonitoringSignificantLocationChangesを使用して重要な変更場所の監視を開始し、「場所変更」イベントが発生するたびに、たとえば、報告された場所から半径500m以内の場所を探すことです。

私が心配しているのは、大幅な場所の変更が発生してバッテリーに影響を与えるたびに、近くの地域のクエリを実行する必要があることです。

もう1つの方法は、場所をstartMonitoringForRegionに登録することですが、Appleは、同時に追跡される領域の数に(合理的な)制限を課しており、20です。 20を大幅に超える場所です。したがって、追跡対象の領域を動的に更新する必要がありますが、それを行うための最善の方法はまだわかりません。

バッテリーの消費量を低く抑えながら、場所の欠落率を低くするために、どのように行うことができるかについてのアイデアはありますか?

31
silentser

質問に対する活動はあまりなかったので、現在この問題をどのように解決しているかを説明します。

新しいリージョンのリロードを重要な場所の変更(SLC)イベントに関連付けました。 SLCが発生すると、「ジオフェンス」する必要がある20の隣接領域をチェックします。最も近い20の地域を見つけるには、次の式に従って緯度と経度の1インチを単純に概算します。

緯度:1度= 110.54 km

経度:1度= 111.320 * cos(緯度)km

監視対象領域の中心について、デバイスの現在位置の境界二乗を確認するだけです(参照: 緯度/経度+ km距離で作業するための簡単な計算?

したがって、たとえば、(10N、10E)がデバイスの現在の場所である場合、(10-1 '、10-1')、(X-10 '、10 + 1')に頂点がある境界正方形から開始します。 、(10 + 1 '、10 + 1')、(10 + 1 '、10-1')(緯度(10N、10E)では、1つの緯度/経度の分は約1,85 kmです)。

20(またはほぼ20)ある場合は、ジオフェンシングに登録し、次のSCLを待ちます。少ない/多い場合は、外接する四角形のサイズを拡大/縮小して、検索を繰り返します。

この検索アルゴリズムを微調整してパフォーマンスを向上させることができますが、ここで説明するものはすでに機能します。

22
silentser

現在監視されているすべての場所を含む「メタジオフェンス」の場所を予約できます。ユーザーがこのジオフェンスを離れると、アプリに通知されます。その後、アプリはそれ自体を更新し、最も遠い領域の追跡を停止し、近くの新しい領域の追跡を開始できます。

8
Dag Høidahl

アプリで20を超えるジオフェンスを使用するための別のオプションを追加すると思いました。この方法は、私たちのアプリで長い間うまく機能しており、組み込みのCLLocationメソッドを使用しています。

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
    if (locations.count > 0) {
        CLLocation *location = locations[0];

        NSMutableArray *sortedFences = [[NSMutableArray alloc] init];

        // add distance to each fence to be sorted
        for (GeofenceObject *geofence in enabledFences) {
            // create a CLLocation object from my custom object
            CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(geofence.latitude, geofence.longitude);
            CLLocation *fenceLocation = [[CLLocation alloc] initWithLatitude:coordinate.latitude longitude:coordinate.longitude];
            // calculate distance from current location
            CLLocationDistance distance = [location distanceFromLocation:fenceLocation];
            // save distance so we can filter array later
            geofence.distance = distance;
            [sortedFences addObject:geofence];
        }

        // sort our array of geofences by distance and add we can add the first 20

        NSSortDescriptor *sortByName = [NSSortDescriptor sortDescriptorWithKey:@"distance" ascending:YES];
        NSArray *sortDescriptors = [NSArray arrayWithObject:sortByName];
        NSArray *sortedArray = [sortedFences sortedArrayUsingDescriptors:sortDescriptors];

       // should only use array of 20, but I was using hardcoded count to exit

        for (GeofenceObject *geofence in sortedArray) {
            CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(geofence.latitude, geofence.longitude);
            CLLocationDistance radius = geofence.radius;
            NSString *ident = geofence.geofenceId;

            CLCircularRegion *fenceRegion = [[CLCircularRegion alloc] initWithCenter:coordinate radius:radius identifier:ident];
            fenceRegion.notifyOnEntry = geofence.entry;
            fenceRegion.notifyOnExit = geofence.exit;
            [locationController.locationManager startMonitoringForRegion:fenceRegion];
        }
    }
}

うまくいけば、これは誰かを助けたり、正しい道に彼らを導くでしょう。

5
Bill Burgess

重要な場所の変更ごとに近接チェックを実行する必要がある場合は、 R-trees または R * -tree のような空間インデックス/検索方法を使用してこれらの検索アルゴリズムは空間的に無関係な領域を除外するため、場所の変更ごとに必要な比較の数。これにより、近接チェックの実行に必要な時間/バッテリーの電力が削減されます。

この投稿は古いことは知っていますが、似たようなことをしたい人のために、 Skyhook は無限の数の会場をジオフェンスする機能を提供します。

マーケティングから:SkyhookのContext Acceleratorを使用すると、アプリ開発者と広告主は、シンプルなウェブインターフェースを介して、Infinite Geofencesを任意のブランドチェーン(CVSなど)または会場カテゴリ(コンビニエンスストアなど)に即座に展開できます。 Skyhookのファーストパーティロケーションネットワークと同じ特許技術を使用して、Context Accelerator SDKは、無限のジオフェンシングを可能にするOSの制限に関係なく、デバイス上のアクティブなジオフェンスを管理します。

1
ChrisD