32

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

实现这一点的一种方法是开始监视重大更改位置,startMonitoringSignificantLocationChanges并且每次触发“位置更改”事件时,查找报告位置半径 500m 内的位置。

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

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

关于如何做到这一点的任何想法,以保持低电池消耗,同时降低位置丢失率?

4

5 回答 5

24

由于在这个问题上没有太多活动,我将描述我们目前如何解决这个问题。

我们将新区域的重新加载与重大位置变化 (SLC) 事件联系起来。当 SLC 发生时,我们会检查 20 个应该被“地理围栏”的相邻区域。为了找到最近的 20 个区域,我们只需根据以下公式近似 1'' 的纬度和经度:

纬度:1 度 = 110.54 公里

经度:1 度 = 111.320 * cos(纬度)公里

并且只需检查设备当前位置的边界正方形以获取监控区域的中心(请参阅:使用纬度/经度 + 公里距离进行简单计算?

因此,例如,如果 (10N,10E) 是设备的当前位置,我们从边界正方形开始,顶点在 (10-1',10-1'), (X-10',10+1') , (10+1',10+1'), (10+1',10-1') (在纬度 (10N,10E) 处,一个纬度/经度分钟大约为 1,85 公里)。

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

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

于 2013-03-08T09:47:02.477 回答
8

您可以为包含所有当前监控位置的“元地理围栏”保留一个位置。当用户离开此地理围栏时,应用程序将收到通知。然后应用程序可以自我更新并停止跟踪最远的区域并开始跟踪附近的新区域。

于 2013-03-07T13:19:21.360 回答
6

我想我会添加另一个选项,以便在您的应用程序中使用 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];
        }
    }
}

希望这将帮助某人或引导他们走上正确的道路。

于 2016-01-06T21:46:13.387 回答
3

如果您担心对每个重大位置更改执行邻近检查,您可以使用空间索引/搜索方法(如R-treesR*-tree)来减少每次位置更改所需的比较次数,因为这些搜索算法将过滤掉(可能很大)空间上不相关的区域。这应该会减少执行接近检查所需的时间/电池电量。

于 2013-09-25T09:02:34.117 回答
2

我知道这篇文章已经过时了,但对于那些想要做类似事情的人来说,Skyhook提供了对无限数量的场地进行地理围栏的能力。

来自他们的营销:Skyhook 的上下文加速器使应用程序开发人员和广告商能够通过简单的 Web 界面立即将无限地理围栏部署到任何品牌链(如 CVS)或场所类别(如便利店)。使用与 Skyhook 第一方定位网络相同的专利技术,上下文加速器 SDK 可以管理设备上的这些活动地理围栏,而不受操作系统限制,从而实现无限地理围栏。

于 2016-04-21T12:25:33.233 回答