30

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

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

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

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区域等的代码,因为我知道当我离开受监控区域超过 100m 时它会起作用。

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

示例区域

有谁知道最小区域半径是否存在限制,或者我做错了什么。

谢谢亚伦

4

9 回答 9

60

我不认为区域监控对于这么小的半径来说效果很好。

  • GPS 芯片的最佳精度kCLLocationAccuracyBestForNavigation通常只有 10 米。
  • Apple 表示(在Location & Maps PG中)区域的最小距离应假定为 200m
  • 我听说区域监控正在使用 WiFi 来获取它的位置(这对省电很有意义)。WiFi精度更像是20m-100m。我不确定让另一个应用程序使用后台位置(即使用 GPS)会如何影响这一点。位置管理器可能会共享信息以提高准确性。
  • 区域监控在一个区域内触发一次可能需要 30 秒,离开一个区域后需要几分钟触发(以防止位置故障触发它)。
  • 当第一次引入区域监控时,他们说它只适用于 100m 的区域,任何更小的区域都会被提升。这可能仍然会发生。
  • 有一个不推荐使用的方法startMonitoringForRegion:desiredAccuracy:,它允许您指定超过区域边界的距离以开始生成通知。据推测,此功能已被引入startMonitoringForRegion:,但仍然存在。一个 10m 的区域可能最终有一个 10m 的缓冲区。
  • 如果您想这样做,请在您要监视的周围指定一个更大的区域,当设备在该区域唤醒时,启动后台位置更新 (GPS) 并使用CLCircularRegion's-containsCoordinate:在设备在 10m 内手动触发。这种方法得到了 Apple 的正式认可(参见WWDC 2013 Session 307)。

CLCircularRegion文档:

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

位置和地图 PG

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

Kevin McMahon的这篇文章还有更多内幕消息,他在 WWDC 2012 的一个实验室向 Core Location 工程师询问了有关区域监控的问题。与此同时,此信息将发生变化,但有关区域类别的部分很有趣。这是一个编辑:

精细区域 (0 - 150m)
- 使用 100m 的地板,此类别的有效范围为 100-150m。
- 对于区域,这种大小的性能在很大程度上取决于与位置相关的硬件
- 在跨越区域边界后,Core Location 检测和调用适当的委托方法所需的时间平均约为 2-3 分钟。
- 一些开发人员已经独立地发现,较小的区域会看到更快的回调,并将较小的区域聚集到一个大区域以改善区域交叉通知。

于 2014-05-29T10:46:59.537 回答
25

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

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

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

在此处输入图像描述

运行应用程序后,您应该会locationManager:didExitRegion在距离监控区域 5319 米处看到火灾。该路线将每 37 分钟循环一次,您会看到设备始终在 5319 米处离开该区域。

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

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

在 iOS 模拟器和 iPhone 5S 上使用测试应用程序时,CLLocationManager 似乎不会以预期的方式触发 didExitRegion 回调。无论被监控的圆形区域的半径如何,回调都不会发生,直到达到大约 5000 米的阈值。

重现步骤:
1. 运行附加的应用程序
2. 通过在 iOS 模拟器中选择 Debug -> Location -> Freeway Drive 启动区域跟踪
3. 监控应用程序。大号 # 表示距观察区域中心的距离。
4. 大约 190 秒和 5300 米后,didExitRegion 将最终开火。

这个问题似乎与该地区的大小无关。根据Apple 文档,甚至支持小区域:

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

尽管区域事件不会立即发生,但它们应该会很快发生。来自苹果文档

跨越区域边界后,区域事件可能不会立即发生。为了防止虚假通知,iOS 在满足某些阈值条件之前不会发送区域通知。具体来说,用户的位置必须跨越区域边界,离开边界最小距离,并在报告通知之前保持在该最小距离至少 20 秒。

这根本不是我在测试工具中看到的。locationManager:didExitRegion在模拟器上,设备在事件发生之前总是距离该区域 5000 多米。

于 2014-05-29T14:32:06.303 回答
17

我喜欢迈克尔和内文的答案。我想从我的个人经验/意见中添加更多信息,以使用区域监控开发基于位置的 iOS 应用程序,并强调一些要点:-

在区域监控上要现实

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

如果你想监控半径只有 10 米的小区域。它可能在一个拥有大量手机信号塔和 wifi 连接区域的高度密集的城市中工作。但同时,信号可能被高塔阻挡,可能会导致信号丢失几秒/分钟,从而导致延迟发送通知。

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

实事求是的监控区域数量

当前的核心位置技术最多只能在单个应用程序上监控20 个区域。确保受监控区域彼此之间也不会太靠近。

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

StackOverFlow 上有一个人想要监控我们地球上的 1800 个点。不要像他一样,他很不切实际,可能不了解当前Core Location技术的局限性。链接检查用户位置是否靠近某些点

微调 LocationManager

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

self.locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
self.locationManager.distanceFilter = kCLDistanceFilterNone;
self.locationManager.activityType = CLActivityTypeAutomotiveNavigation;

kCLLocationAccuracyBestForNavigation会消耗更多的电池kCLLocationAccuracyBest。但是,它会更准确。

当在不同的受监控区域同时触发多个通知时,我发现iOS 7中的区域监控出现故障。我找到了过滤掉这个故障的解决方案。欲了解更多信息,请访问:iOS 7 上的区域监控故障 - 同时多个通知

不要过于雄心勃勃

您可能使用过一些可以监控小区域的应用程序,这些应用程序非常准确,并且能够在您进入该区域的同一秒通知您。你有灵感开发完全相同的应用程序来与他们竞争。但是你了解幕后发生的事情吗?他们正在使用哪些其他技术?他们正在与哪些合作伙伴合作?

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

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

注意:我只想分享我的 2 美分。以上信息由我的经验和个人意见组成。它可能不是 100% 准确,因为我仍在学习Core Location and Region Monitoring

于 2014-06-03T03:51:22.137 回答
6

我同意Michael G. Emmons的观点,也想分享我的经验:

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

在此处输入图像描述

解释行为:

  • 我当前的位置是 Region-1,我开始监视上述三个区域,并调用 requestStateForRegion 来确定里面是否有任何区域,我现在所在的位置。
  • 然后我收到前两个区域(区域 1 和区域 2)的“输入”通知,但它应该只检测区域 1。
  • 现在,当我进入 region-2 时,我收到了 region-3 的 Enter 通知。但我应该在这里收到 region-2 的通知。
  • 现在,当我再次进入 region-1 时,我得到了为 region-3 触发的 Exit 事件,并且继续。
  • 但我没有收到前两个区域的任何进入/退出事件,直到我从前两个区域移动至少超过 7 公里到 10 公里。

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

我的假设:

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

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

请更新我,如果有人解决了这个问题,或者 Apple 文档关于这个问题的任何地方。

于 2014-09-16T08:23:22.730 回答
2

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

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

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

具体的阈值距离由硬件和当前可用的定位技术决定。例如,如果禁用 Wi-Fi,则区域监控的准确性会大大降低。但是,出于测试目的,您可以假设 最小距离约为 200 米

于 2017-11-03T15:22:18.927 回答
2

基于@Nevan的回答,这表明WWDC 2013 307中的某种覆盖范围(没有直接解决这个问题),我想出了一个合理的解决方案来获得< 10m的到达某个位置的准确度,尽管我有一种感觉该实施-(void)locationManager:didVisit:可能会使这更加节省电池电量,但会提供较少的更新。

首先,有一些半径为 0..150m 的区域,并开始监测。没关系,因为系统似乎在 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];
}
于 2016-06-09T17:26:05.253 回答
1

听起来即使是 1 米也应该可以工作(并且在 iPhone 4S+ 设备上工作得更好):

startMonitoringForRegion:

(...)

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

于 2014-05-29T00:43:44.567 回答
0

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

不幸的是,在信号塔和 wifi 网络很少的地区,情况正好相反。例如,我的社区大约有 1000 米宽和 500 米高(1KM x 0.5KM),里面没有手机信号塔。在社区周围的周边几乎没有手机信号塔。不幸的是,在社区周边,地理围栏服务没有检测到任何东西

不用说,我正在设备上启用 Wifi 进行测试。

当我在 Android 上测试我的应用程序时:android 4.3、4.4 和 5.1 上的地理围栏服务比 iOS 上运行得更好。Android 的地理围栏服务不会检测到 100% 的区域转换,但它会检测到 50%-90% 的区域转换。

我得出以下结论:如果会有更多的手机信号塔和 Wifi 热点,如果 Apple 会改进地理围栏服务,那么 iOS 设备上的检测将与 Android 设备上的一样好。

于 2015-02-12T16:58:16.613 回答
-2

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

因此,您可以定义的最小区域取决于基站之间的距离。

在购物中心或体育场内,它可能可以走 10 米——手机信号塔通常非常靠近。在偏远地区,任何小于 100 公里的东西都可能失败。

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

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

于 2014-05-28T08:57:13.123 回答