iOS地理围栏,监控开始时如何处理区域内?



我一直无法弄清楚如何处理呼叫时电话已经在区域内的情况startMonitoringForRegion?其他问题建议在内部调用requestStateForRegiondidStartMonitoringForRegion然后调用该方法didDetermineState: forRegion:。所以代码看起来像这样:

- (void)viewDidLoad {
//location manager set up etc...
for (Object *object in allObjects){
CLRegion *region = [self geofenceRegion:object];
[locationManager startMonitoringForRegion:region];
}
}
- (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region {
[self.locationManager requestStateForRegion:region];
[self.locationManager performSelector:@selector(requestStateForRegion:) withObject:region afterDelay:5];
}
- (void)locationManager:(CLLocationManager *)manager
didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region {
if (state == CLRegionStateInside){
[self locationManager:locationManager didEnterRegion:region];
}  
}

现在显然,geofenceRegion方法是我自己的,它工作正常,并且对象包含纬度和半径之类的东西,并且所有工作正常,所以这不是这里的问题。

无论如何,上述代码的问题在于,如果用户在将区域添加到他们的设备时已经在区域内,它确实有效(即didEnterRegion已完成)。但是,问题是每次根据Apple文档越过其中一个边界区域时,也会调用方法didDetermineState: forRegion:

每当区域存在边界转换时,位置管理器都会调用此方法。除了调用 locationManager:didEnterRegion: 和 locationManager:didExitRegion: 方法之外,它还调用此方法。位置管理器还调用此方法以响应对其异步运行的请求状态区域:方法的调用。

现在,由于每次输入区域时,都会自动调用didEnterRegion,但随后会再次调用didDetermineState: forRegion:因为根据苹果文档也会自动调用这会导致再次调用didEnterRegion因此当我只想输入一次区域时,该区域被输入两次。我怎样才能避免这种情况?

感谢您的帮助。

溶液

解决方案真的很简单,我只是以错误的方式去做。我不得不选择使用didEnterRegion:didExitRegion的两种方法,或者使用didDetermineState: forRegion并创建自己的进出区域的方法,两者都不应该使用

所以我选择只使用didDetermineState: forRegion方法,我的代码现在看起来像这样:

请注意,使用此方法,如果不在内部,则将为该区域调用退出区域,如果像我一样,您只希望在输入发生后退出,您将需要某种方法来检查区域是否已输入(我自己使用核心数据,因为我已经在使用它来存储区域的其他方面)。

- (void)viewDidLoad {
//location manager set up etc...
for (Object *object in allObjects){
CLRegion *region = [self geofenceRegion:object];
[locationManager startMonitoringForRegion:region];
}
}
- (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region {
[self.locationManager performSelector:@selector(requestStateForRegion:) withObject:region afterDelay:5];
}
- (void)locationManager:(CLLocationManager *)manager
didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region {
if (state == CLRegionStateInside){
[self enterGeofence:region];
} else if (state == CLRegionStateOutside){
[self exitGeofence:region];
} else if (state == CLRegionStateUnknown){
NSLog(@"Unknown state for geofence: %@", region);
return;
}
}
- (void)enterGeofence:(CLRegion *)geofence {
//whatever is required when entered
}
- (void)exitGeofence:(CLRegion *)geofence {
//whatever is required when exit
}

只是不要使用 locationManager:didEnterRegion:因为 locationManager:didDetermineState:forRegion: 为您提供触发输入代码所需的所有信息,顺便说一下,它不应该是locationManager:didEnterRegion:,使用您自己的选择器,它不是CLLocationManagerDelegate协议的一部分。

另一种方法是在开始监视区域时测试区域内部位置。这个解决方案并不像听起来那么简单:您需要首先通过调用startUpdatingLocation来更新当前位置,因为仅读取locationManager的位置属性可能会给您过时或极其不准确的读数。

最新更新