iOS Geofence CLCircularRegion监控。 locationManager:didExitRegion似乎没有按预期工作

时间:2014-05-26 08:40:39

标签: ios core-location cllocationmanager geofencing clcircleregion

我目前正试图让我的应用程序使用CoreLocation来监控特定区域但是我发现它似乎没有按预期工作,在我看来,它无法使用小的半径设置为每个位置,即10米。

我还整理了一个小测试应用程序,在地图上绘制圆半径,这样我就可以直观地看到发生了什么。

我用于监控位置的代码如下:

self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;

// Set-up a region
CLLocationDegrees latitude = 52.64915;
CLLocationDegrees longitude = -1.1506367;
CLLocationCoordinate2D centerCoordinate = CLLocationCoordinate2DMake(latitude, longitude);

CLCircularRegion *region = [[CLCircularRegion alloc] initWithCenter:centerCoordinate
                                                                 radius:10 // Metres
                                                             identifier:@"testLocation"];

[self.locationManager startMonitoringForRegion:region];

我没有在DidEnter区域等处提供代码,因为我知道当我离监控区域超过100米时,该代码有效。

这是应用程序的屏幕截图,当我距离地图上的紫色位置超过10米时,确实的退出区域事件不会触发,但是如果我将位置切换到它会激活伦敦,当我将位置设置回蓝色位置时,它也会触发。

Example Region

有没有人知道最小区域半径是否有限制,或者我做错了。

谢谢Aaron

9 个答案:

答案 0 :(得分:50)

我认为区域监测不会对这么小的半径有效。

  • GPS芯片和kCLLocationAccuracyBestForNavigation的最佳精度通常只有10米。
  • Apple说(在Location & Maps PG中)区域的最小距离应假定为200米
  • 我听说区域监控正在使用WiFi来获取它的位置(这对于省电是有意义的)。 WiFi精度更像是20m-100m。我不确定如何使用其他应用程序使用背景位置(即使用GPS)会影响这一点。也许,位置经理会共享信息以提高准确性。
  • 区域监控可能需要30秒才能在区域内点火一次,并且在离开区域后需要几分钟才能点火(以防止位置故障触发它)。
  • 当首次引入区域监测时,他们说它只适用于100米区域,任何较小的区域都会被抬高。这可能仍然会发生。
  • 有一种弃用的方法startMonitoringForRegion:desiredAccuracy:,它允许您指定区域边界以外的距离以开始生成通知。据推测,此功能已归入startMonitoringForRegion:,但仍然存在。一个10米的区域最终可能会有10米的缓冲区。
  • 如果要执行此操作,请在要监控的位置周围指定一个更大的区域,当设备在该区域唤醒时,启动后台位置更新(GPS)并使用CLCircularRegion的{​​{1当设备手动在10米范围内时触发。这种方法由Apple正式批准(见WWDC 2013会议307)。

来自-containsCoordinate:文档:

  

请记住,位置管理器在跨越区域边界时不会立即生成通知。相反,它应用时间和距离标准来确保交叉是有意的并且应该真正触发通知。因此,请选择合适的中心点和半径,并给您足够的时间提醒用户。

来自Location & Maps PG

  

区域事件可能不会在超过区域边界后立即发生。为防止虚假通知,iOS在满足某些阈值条件之前不会发送区域通知。具体而言,用户的位置必须越过区域边界,离开边界最小距离,并在报告通知之前保持最小距离至少20秒。
  特定阈值距离由当前可用的硬件和定位技术确定。例如,如果禁用Wi-Fi,则区域监控的准确性要低得多。但是,出于测试目的,您可以假设最小距离约为200米。

还有来自this post by Kevin McMahon的内幕消息,他向核心位置工程师询问了WWDC 2012实验室的区域监控情况。此信息在此期间会发生变化,但有关区域类别的部分很有意思。这是一个编辑:

  

精细区域(0 - 150米)
    - 在100米的楼层,这个类别的范围实际上是100-150米     - 对于区域而言,这种尺寸性能在很大程度上取决于与位置相关的硬件     - 超越区域边界后,Core Location检测并调用适当的委托方法所花费的时间大约为2-3分钟。
    - 一些开发人员已经独立地发现,较小的区域会看到更快的回调,并且会聚集较小的区域以覆盖一个大区域以改善区域交叉通知。

答案 1 :(得分:24)

这似乎是CLLocationManager中的错误。我已经使用各种区域半径配置进行了大量测试,并且locationManager:didExitRegion没有以预期方式触发。这似乎是一个相当讨厌的错误或区域监控根本没有像文档建议那样发生。我有任何想要它的人都可以使用测试工具:

http://www.mediafire.com/download/x863zkttltyalk6/LocationTest.zip

在模拟器中运行它并通过选择Debug - >开始测试。位置 - > iOS模拟器菜单中的高速公路驱动器。您看到的数字是距受监控区域中心的距离。设备位于受监控区域内时背景颜色为绿色,区域外时背景颜色为红色。距离下方的文本是事件日志。

enter image description here

运行应用程序后,您应该会在距受监控区域5319米处发现locationManager:didExitRegion点火。该路线将每37分钟循环一次,您将看到离开该地区的设备总是在5319米处。

我已经提交了radar with Apple (17064346)。一旦我收到他们的回复,我会更新这个答案。至少那时我们会从规范来源获得一些意见。

以下是发送给Apple的详细文字:

  

在iOS模拟器和iPhone 5S上使用测试应用程序   CLLocationManager似乎没有触发didExitRegion回调   预期的方式。无论圆形区域的半径是多少   监控后,回调将不会发生,直到大约5000的阈值   米被击中了。

     

重现步骤:
  1.运行附加的应用程序
  2.选择Debug - >开始区域跟踪。位置 - > iOS模拟器中的高速公路驱动器
  3.监控应用程序。大#表示距监视区域中心的距离   在大约190秒和5300米之后,退出会最终开火。

该问题似乎与该地区的规模无关。根据{{​​3}},甚至支持小区域:

  

在iOS 6中,半径在1到400米之间的区域效果更好   在iPhone 4S或更高版本的设备上。 (在iOS 5中,具有半径的区域   在iPhone 4S和更高版本的设备上,1到150米之间的效果会更好。)   在这些设备上,应用程序可以期望接收适当的区域   在3到5分钟内输入或区域退出通知   平均,如果不是更快。

虽然区域事件不会立即发生,但它们应该很快发生。来自Apple docs

  

区域事件可能不会在区域边界后立即发生   交叉。为防止虚假通知,iOS不提供区域   通知,直到满足某些阈值条件。   具体来说,用户的位置必须跨越区域边界,移动   远离边界最小距离,并保持在那   通知之前至少20秒的最小距离   报道。

这完全不是我在测试工具中看到的。在模拟器上,在locationManager:didExitRegion事件发生之前,设备将始终距离该区域5000米以上。

答案 2 :(得分:16)

我喜欢Michael和Nevan的答案。我想通过区域监控开发基于位置的iOS应用程序,从我个人的经验/意见中添加更多信息,并重点介绍一些要点: -

在区域监控方面切合实际

区域监控正在使用全球定位系统(GPS),Wifi和其他技术来确定设备是在受监控区域内还是外。不要忘记我们的地球是510平方公里,大约30%是土地(1.49亿平方公里)。这是一个巨大的领域。还记得最近的MH370丢失案吗?我们目前最先进的技术甚至无法确定丢失飞机的估计区域。

如果您想监控只有 10米半径的小区域。它可能在一个高密度城市内工作,有很多手机信号塔和无线连接区域。但与此同时,信号可能被高层塔阻挡,这可能导致信号丢失几秒/分钟,从而导致通知延迟。

因此,在决定要监控的区域有多大之前,您必须考虑上述信息。我个人认为10米半径太小了。

在受监控区域数量上实现

目前的Core Location技术只能在一个应用上监控最多最多20个区域。确保受监控的区域也不要太靠近。

我个人测试了3个半径约100米的区域,这些区域彼此相差约200米。有时,当我开车经过时,我可以收到来自所有这3个地区的通知,但有时候,我只能从第一个地区收到通知。可能是什么原因?我不知道。这些地区可能彼此太靠近。或者手机信号塔决定我的设备实际上并不在受监控区域内。

StackOverFlow上有一个人想监视我们地球上的1800点。不要像他一样,因为他非常不现实,可能不理解当前Core Location技术的局限性。 链接Check if the user location is near of some points

微调LocationManager

如果您的应用需要监控小区域或需要经常更新位置。以下是您的位置管理器的潜在属性。

self.locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
self.locationManager.distanceFilter = kCLDistanceFilterNone;
self.locationManager.activityType = CLActivityTypeAutomotiveNavigation;
kCLLocationAccuracyBestForNavigation相比,

kCLLocationAccuracyBest会消耗更多电量。但是,它会更准确。

当在不同的受监控区域同时触发多个通知时,我发现iOS 7中区域监控出现故障。我找到了一个解决这个故障的解决方案。有关详细信息,请访问:Region Monitoring Glitch on iOS 7 - Multiple Notifications at the same time

不要过于雄心勃勃

您可能已经使用了一些可以监控小区域的应用程序,并且非常准确,并且能够在您踏入该区域的同一时间通知您。而且你有灵感来开发完全相同的应用程序来与它们竞争。但是你明白幕后发生了什么吗?他们使用了哪些其他技术?和他们合作的伙伴是什么?

我对此做了一些研究,发现他们使用的一些技术不公开。其中一些公司资金雄厚,可以向电信公司支付额外费用,以便获得最佳的位置准确性,从而获得最佳用户体验。我不明白它是如何工作的细节。我相信大多数位置确定实际上是在服务器端(后端),而不是移动(前端)。

因此,这些公司开发的应用程序不仅可以确定最准确的位置,而且不会消耗大量电池。

注意:我只是想分享我的2美分。以上信息包括我的经验和个人意见。它可能不是100%准确,因为我仍在学习核心位置区域监控

答案 3 :(得分:5)

我同意 Michael G. Emmons ,并希望分享我的经验:

我用三个区域测试了我的代码,如下图所示:

enter image description here

解释行为:

  • 我当前的位置是Region-1,我开始监控以上内容 三个区域,并调用requestStateForRegion,以确定,如果里面有任何区域,我当前站在哪里。
  • 然后我得到"输入"通知,对于前两个区域(区域1和区域2),但它应该只检测区域-1。
  • 现在当我进入区域2时,我收到了区域-3的输入通知。但是我应该在这里收到关于region-2的通知。
  • 现在当我再次进入区域1时,我获得了为区域-3触发的Exit事件,并且这种情况仍在继续。
  • 但是我没有获得前两个区域的任何进入/退出事件,直到距离前两个区域至少超过7Km-10Km。

预期行为:   - 只有当我越过区域边界或区域内,而不是距离该区域500米之前,才应触发进入/退出事件。

我的假设:

  • 在所有实验之后我注意到的是,当我打电话时 " requestStateForRegion"对于所有三个地区,
  • 它检测半径为5000m的区域内的所有区域,这就是它的原因 同时检测前两个区域(区域-1创建一个圆圈 半径5000米,区域-2在其范围内,这就是为什么区域-2 也被发现了。)
  • 当用户移动距离超过10公里时,将调用他们的Exit事件,当用户返回这些区域时,将触发他们的Enter事件。与上面 Aaron Wardle 所解释的情况相同。
  • 区域-3被检测到,因为当用户进入区域-1时,即。距离region-3 8-9km,因此为此事件触发了Exit事件,当用户在区域2的路线上时,即使区域-3距离5000米,仍然会检测到区域-3并且发射,输入region-3的事件。

所以我认为5000米内的所有区域都被检测到,并且当用户从检测到的区域移开10公里时,其Exit事件将被触发。否则,如果用户在5Km范围内,它将永远不再称之为进入/退出事件。

如果有人解决了这个问题,请更新我,或者就此问题随时随地向Apple提供文件。

答案 4 :(得分:2)

这更像是一个重要的评论。来自Region Monitoring and iBeacon

测试iOS应用程序的区域监控支持

  

在iOS模拟器中测试您的区域监控代码时   设备,意识到区域事件可能不会立即发生   区域边界交叉。为了防止虚假通知,iOS   在某个阈值之前不会发送区域通知   条件得到满足。具体来说,用户的位置必须越过   区域边界,离开边界最小距离,   和保持在最小距离之前至少20秒   报告通知

     

特定阈值距离由硬件确定   目前可用的定位技术。例如,   如果 Wi-Fi被禁用,则区域监控显着减少   准确即可。但是,出于测试目的,您可以假设   最小距离约为200米

答案 5 :(得分:1)

Sounds甚至1米应该可以工作(并且在iPhone 4S +设备上工作得更好):

  

<强> startMonitoringForRegion:

     

(...)

     

在iOS 6中,半径在1到400米之间的区域在iPhone 4S或更高版本的设备上运行得更好。 (在iOS 5中,半径在1到150米之间的区域在iPhone 4S和更高版本的设备上运行得更好。)在这些设备上,应用程序可以在3到5分钟内平均接收输入的适当区域或区域退出通知,如果不是更快。

答案 6 :(得分:1)

根据@ Nevan的回答,它表明在WWDC 2013 307(没有直接解决这个问题)的某种覆盖范围,我提出了一个合理的解决方案来获得&lt;到达某个位置的准确度为10米,但我觉得实施-(void)locationManager:didVisit:可能会使电池更加保守,但会提供更少的更新。

首先,有一些半径为0..150米的区域,并开始监控。并不重要,因为系统似乎在150~200m左右触发这些:

_locationManager = [[CLLocationManager alloc] init];
_locationManager.delegate = self;

CLCircularRegion *region = [[CLCircularRegion alloc] initWithCenter:CLLocationCoordinate2DMake(location.lat, location.lng) radius:50 identifier:location.name];
[_locationManager startMonitoringForRegion:region];

然后,实施

-(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region {
    for (CLCircularRegion *enteredRegion in _locationManager.monitoredRegions.allObjects) {
        if ([enteredRegion.identifier isEqualToString:region.identifier]) {

            self.locationManager.activityType = CLActivityTypeFitness;
            self.locationManager.distanceFilter = 5;
            [self.locationManager startUpdatingLocation];

            break;
        }
    }
}

系统将开始监控并向您的代表报告位置流,即使您的应用已暂停(需要UIBackgroundModes包含location数组元素)。

要检查其中一个位置是否位于您所在地区的中心,请执行:

-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
    CLLocation *firstLocation = [locations firstObject];
    CGFloat const DESIRED_RADIUS = 10.0;

    CLCircularRegion *circularRegion = [[CLCircularRegion alloc] initWithCenter:firstLocation.coordinate radius:DESIRED_RADIUS identifier:@"radiusCheck"];

    for (CLCircularRegion *enteredRegion in _locationManager.monitoredRegions.allObjects) {
        if ([circularRegion containsCoordinate:enteredRegion.center]) {
            [_locationManager stopUpdatingLocation];
            NSLog(@"You are within %@ of %@, @(DESIRED_RADIUS), enteredRegion.identifier);            
            break;
        } else if ([enteredRegion containsCoordinate:circularRegion.center]) {
            NSLog(@"You are within the region, but not yet %@m from %@", @(DESIRED_RADIUS), enteredRegion.identifier);
        }
    }
}

您还需要实施:

-(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region {
    [_locationManager stopUpdatingLocation];
}

答案 7 :(得分:0)

在过去的几天里,我一直在测试我的iOS 8.1设备(iPhone 5S)上的地理围栏功能,以便开发一款应用程序。
该应用程序正在向iOS gefence服务注册少数几个区域。应用程序的逻辑需要每个地理围栏半径在40到80米之间 到目前为止,我看到在具有更多蜂窝塔和Wifi热点的地区,地理围栏检测在进入地区时已经足够好了。也就是说,在城镇地区,商业区等地区,地理围栏检测工作正常。

不幸的是,相反的情况发生在电池塔和电池塔很少的区域。 wifi网络。例如,我的社区宽约1000米,高度约为500米(1KM x 0.5KM),其中没有没有蜂窝塔。在附近的周边,人们认为很少有蜂窝塔。不幸的是,在邻域的周边,地理围栏服务检测到 nothing

毋庸置疑,我正在设备上启用Wifi进行测试。

当我在Android上测试我的应用程序时:android 4.3,4.4&amp;的geofencing服务5.1的效果比在iOS上好得多。 Android的地理围栏服务没有检测到100%的区域过渡,但它检测到50%-90%的区域过渡。

我总结如下:如果有更多的手机信号塔和Wifi热点&amp;如果Apple改进了地理围栏服务,那么iOS设备上的检测就会像Android一样好。

答案 8 :(得分:-2)

地理围栏的工作原理是检测用户从一个小区网络塔移动到另一个小区网络塔。

因此,您可以定义的最小区域取决于细胞塔的距离。

在购物中心或体育场内,它可能可以做10米 - 牢房塔通常非常靠近。在区域内,任何小于100公里的地方都可能失败。

如果您需要更小的区域,则需要使用蓝牙而不是手机信号塔(iBeacons)。如果目标区域中有蓝牙低能耗设备,您可以将范围设置为非常短(厘米)或相当大(最多30米左右)。请注意,这一切都取决于iBeacon硬件的质量,有些比其他硬件要好。

不幸的是,蓝牙(4.0或更新版本)和蜂窝网络塔是监控位置而不会显着耗尽电池的唯一方法。即使屏幕关闭,保持GPS激活以检查10米的边界也会在约2小时内将电池从完全耗尽到完全平坦。