iOS Geofence, how to handle when inside region when monitoring starts?
当调用 startMonitoringForRegion 时,我一直无法弄清楚如何处理手机已经在区域内的情况?其他问题建议在 didStartMonitoringForRegion 中调用 requestStateForRegion,然后调用方法 didDetermineState: forRegion:。所以代码看起来像这样:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
– (void)viewDidLoad {
//location manager set up etc… for (Object *object in allObjects){ CLRegion *region = [self geofenceRegion:object]; – (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region { [self.locationManager requestStateForRegion:region]; – (void)locationManager:(CLLocationManager *)manager if (state == CLRegionStateInside){ |
现在很明显,geofenceRegion 方法是我自己的,它工作正常,并且对象包含诸如 lat long 和 radius 之类的东西,而且一切正常,所以这不是这里的问题。
无论如何,上述代码的问题在于,如果用户在将区域添加到他们的设备时已经在该区域内(即,didEnterRegion 已完成),它确实可以工作。然而问题是,每次越过边界区域之一时,也会调用方法 didDetermineState: forRegion: 根据苹果文档:
The location manager calls this method whenever there is a boundary transition for a region. It calls this method in addition to calling the locationManager:didEnterRegion: and locationManager:didExitRegion: methods. The location manager also calls this method in response to a call to its requestStateForRegion: method, which runs asynchronously.
因此,每次输入区域时,都会自动调用 didEnterRegion,但随后会再次调用它,因为根据 Apple 文档,还会自动调用 didDetermineState: forRegion:,这会导致再次调用 didEnterRegion 所以当我只想输入一次时,该区域被输入了两次。我怎样才能避免这种情况?
感谢您的帮助。
解决方案
解决方案真的很简单,我只是以错误的方式去做。我必须选择使用两种方法 didEnterRegion: 和 didExitRegion 或使用 didDetermineState: forRegion 并创建我自己的方法来进入和退出该区域,两者都不应该使用。
所以我选择只使用 didDetermineState: forRegion 方法,我的代码现在看起来像这样:
请注意,如果区域不在内部,则使用此方法将调用退出区域,如果像我一样,您只想在输入发生后退出,您将需要某种方法来检查该区域是否有已经输入(我自己使用核心数据,因为我已经使用它来存储区域的其他方面)。
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
– (void)viewDidLoad {
//location manager set up etc… for (Object *object in allObjects){ CLRegion *region = [self geofenceRegion:object]; – (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region { [self.locationManager performSelector:@selector(requestStateForRegion:) withObject:region afterDelay:5]; – (void)locationManager:(CLLocationManager *)manager if (state == CLRegionStateInside){ [self enterGeofence:region]; } else if (state == CLRegionStateOutside){ [self exitGeofence:region]; } else if (state == CLRegionStateUnknown){ – (void)enterGeofence:(CLRegion *)geofence { //whatever is required when entered – (void)exitGeofence:(CLRegion *)geofence { //whatever is required when exit |
- 受此元帖子的约束。最好不要在问题本身中包含答案。要么写一个单独的答案,要么只接受给定的答案或写评论。
根本不要使用 locationManager:didEnterRegion:,因为 locationManager:didDetermineState:forRegion: 为您提供了触发 on-entry 代码所需的所有信息,顺便说一下,它不应该是 locationManager:didEnterRegion: ,使用您自己的选择器,它不是 CLLocationManagerDelegate 协议的一部分。
另一种方法是在开始监视区域时测试区域内的位置。这个解决方案并不像听起来那么简单:您需要首先通过调用 startUpdatingLocation 来更新当前位置,因为仅读取 locationManager 的 location 属性可能会给您带来陈旧或极其不准确的读数。
- 如果我必须自己跟踪它,那么 API 的意义何在?这似乎根本不合逻辑?
- API 描述清楚地表明它监视进入和退出事件。您希望获得比 API 更多的东西,即在从区域内部开始监控时触发 entry 事件。有一个较低级别的 API 回调, locationManager:didDetermineState:forRegion: 你可以使用它,但是尝试将它与更高级别的东西结合起来会带来麻烦。
- 但是正如我在我的问题中提到的那样,在进入或退出区域时也会触发 didDetermineState。所以你的意思是当我开始监控一个区域时我必须手动获取当前位置,如果这个当前位置在该区域内,我自己处理。忽略 requestStateForRegion?。我想我只是想不出如果不使用区域监控你还会使用 requestStateForRegion 做什么
- requestStateForRegion 完全按照它在锡上所说的那样做——它请求一个区域的状态。如果没有这种方法,您将不得不开始标准位置更新,继续处理这些更新,直到获得所需精度的读数,然后停止更新,然后您必须检查该位置是否在区域圈内。
- 但是,如果您还没有监控它,为什么还要请求一个区域的状态呢?
- 因为您想知道刚开始监视时您是否已经在该区域内。就像我说的那样,另一种方法是采取额外的步骤来确定位置。
- 这正是我想要做的,但就像我说的,在监控区域时,它会在每次跨越区域边界时调用 didDetermineStateForRegion。因此,如果在此函数中您告诉它进入区域,它将进入该区域两次。对不起,我觉得我没有正确解释这个
- Joe,我建议您只使用一种方法:didDetermineStateForRegion 或 didEnterRegion/didExitRegion,但不能同时使用。顺便说一句,您不需要两个不同的”未知”状态,因为您希望在进入状态时触发入口代码。我稍后会更新答案。可能这就是混乱的根源。
- 谢谢亚历克斯的所有帮助,我已经用我如何实施你的解决方案更新了我的答案
来源:https://www.codenong.com/30282259/