使用iOS地理围栏跟踪多个(20+)位置

sil*_*ser 30 location cllocationmanager ios geofencing

iOS应用程序使用地理围栏来通知用户有关预定义的附近位置.允许应用程序错过某个位置(用户没有收到有关附近位置的通知),但是希望保持较低的丢失率.

实现这一目标的一种方法是开始监控重要的变更位置,startMonitoringSignificantLocationChanges并且每次"位置变更"事件被触发时,查找位于报告位置的500米半径内的位置.

令我担心的是,每次发生重大位置变化时都需要对附近区域执行查询,这会影响电池.

另一种方法是注册地点,startMonitoringForRegion但Apple对同时跟踪的地区数量(合理)限制为20,我们有超过20个地点.因此需要对跟踪区域进行某种动态更新,但我仍然不确定最佳方法是什么.

有关如何做到这一点的任何想法,以便它保持低电池消耗,但也具有低位置的丢失率?

sil*_*ser 22

由于在这个问题上活动不多,我将描述我们目前如何解决这个问题.

我们将新区域的重新加载与重要的位置变更(SLC)事件联系在一起.当SLC发生时,我们检查应该"地理围栏"的20个相邻区域.为了找到20个最接近的区域,我们根据以下公式简单地逼近纬度和经度的1'':

纬度:1度= 110.54公里

经度:1度= 111.320*cos(纬度)km

然后检查设备当前位置的边界平方,以便监控区域的中心(参见:使用lat/lon + km距离进行简单计算?)

因此,例如,如果(10N,10E)是设备的当前位置,我们从边界处开始,顶点位于(10-1',10-1'),(X-10',10 + 1') ,(10 + 1',10 + 1'),(10 + 1',10-1')(在纬度(10N,10E),一个纬度/经度分钟接近1,85 km).

如果有20个(或差不多20个) - 我们将它们注册为地理围栏并等待下一个SCL.如果更少/更多,只需增加/减少边界矩形的大小并重复搜索.

您可以调整此搜索算法以获得更好的性能,但此处描述的搜索算法已经完成了这项工作.

  • 你能不能把一些示例代码展示出来怎么做? (6认同)
  • 由于您已经在使用重要的位置更改事件,为什么不完全跳过iOS地理围栏?你可以自己检查一下你的地理位置是否在其中,而不是找到最近的地理围栏. (2认同)
  • SLC事件通常不足以用作地理围栏的完全替代品.我将补充说我们遇到了同样的问题但是以不同的方式解决了它.我们使用SLC中的位置对象,并使用内置的位置管理器方法计算与这些坐标最接近的20.丢掉旧的20并添加最近的20. (2认同)

Dag*_*ahl 8

您可以为"meta-geofence"保留一个位置,其中包含所有当前监控的位置.当用户离开此地理围栏时,将通知应用程序.然后,应用程序可以更新自己并停止跟踪最远的区域并开始跟踪附近的新区域.

  • 我写了一个遵循上述方法的解决方案:http://stackoverflow.com/questions/22297995/add-more-than-20-regions-to-geofencing-ios/24080059#24080059 (2认同)

Bil*_*ess 5

我想我会添加另一个选项,在您的应用中使用超过20个Geofences.这种方式在我们的应用程序中已经运行了很长时间,并使用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];
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

希望这将有助于某人或引导他们走上正确的道路.

  • 比尔,我正在读你的解决方案.你只是调用"startMonitoringForRegion:"而不是"stopMonitoringForRegion:".如果20个地区已经注册但下一次通话我会尝试注册一个新地区会怎样?存储所有已注册的区域并在调用"startMonitoringForRegion:"之前为新的20个最近坐标停止之前已注册的所有区域是不是有意义? (2认同)