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

Posted

技术标签:

【中文标题】使用 iOS 地理围栏跟踪多个(20 多个)位置【英文标题】:Tracking multiple (20+) locations with iOS geofencing 【发布时间】:2012-12-23 08:27:19 【问题描述】:

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

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

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

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

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

【问题讨论】:

我也很想知道如何做到这一点。 如需快速回答,请参阅here 【参考方案1】:

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

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

纬度:1 度 = 110.54 公里

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

只需检查设备当前位置的边界正方形是否为受监控区域的中心(参见:Simple calculations for working with lat/lon + km distance?)

因此,例如,如果 (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。如果更少/更多,只需增加/减少边界矩形的大小并重复搜索。

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

【讨论】:

我正在尝试做同样的事情,但在应用程序关闭时对我不起作用,它只是在应用程序处于后台时工作。我非常感谢发布一些示例代码,谢谢。 既然您已经在使用重要的位置更改事件,为什么不完全跳过 iOS 地理围栏?您可以自己检查自己是否在某个地理围栏内,而不是查找最近的地理围栏。 SLC 事件的触发频率不足以完全替代地理围栏。我会补充一点,我们有同样的问题,但以不同的方式解决了它。我们使用 SLC 中的位置对象,并使用内置的位置管理器方法计算最接近这些坐标的 20。扔掉旧的 20 并添加最接近的新 20。【参考方案2】:

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

【讨论】:

我在这里写了一个遵循上述方法的解决方案:***.com/questions/22297995/… @uofc 你的解决方案在那个页面的哪里? 如果手机将该元地理围栏置于某种不良状态(例如关闭),您将不会收到通知,并且会在下一次应用启动之前死亡。【参考方案3】:

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

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

【讨论】:

嗨,比尔,我刚刚在阅读您的解决方案。您只调用“startMonitoringForRegion:”而不是“stopMonitoringForRegion:”。如果已经注册了 20 个区域,但在下一次通话中我尝试注册一个新区域,会发生什么情况?存储所有已注册的区域并在调用“startMonitoringForRegion:”之前存储所有已注册的区域是否有意义,以便新的 20 个最近坐标停止之前已注册的所有区域? 只有当我有超过 20 个并且我的应用程序进入后台时,我才会调用 startMonitoring。当我的应用返回 (-becomeActive) 时,我将其关闭。我不断地关闭地理围栏并重新打开它们。当我添加地理围栏时,我不会直接将其添加到可能失败的位置。我基本上将其设置为启用,然后告诉我的经理添加最接近的 20 个。 YMMV 你能用 Swift 回答吗 Obj-C 中使用的所有东西都应该在 Swift 中可用。转换应该不会太难。 @RobertWeindl 使用locationManager.monitoredRegions,您可以获取当前正在监控的区域并将其全部删除。【参考方案4】:

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

【讨论】:

【参考方案5】:

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

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

【讨论】:

以上是关于使用 iOS 地理围栏跟踪多个(20 多个)位置的主要内容,如果未能解决你的问题,请参考以下文章

使用新的 Android API 跟踪 100 多个同步地理围栏

位置更新在后台停止 - iOS

Android - 需要添加超过 100 个地理围栏

Android:如何让用户为其他被跟踪用户创建地理围栏?

安卓地理围栏

iOS蓝色状态栏同时使用地理围栏/背景位置更新来触发通知