- (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方法是我自己的并且它工作正常,并且对象包含lat long和radius之类的东西,并且一切都很好,所以这不是问题.
无论如何,上面代码的问题在于,如果用户在将区域添加到其设备时已经在区域内(即完成了didEnterRegion),它确实有效.但问题是,每次根据apple docs划分其中一个边界区域时,方法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,然后再次调用它,因为didDetermineState:forRegion:也会根据apple docs自动调用,这会导致再次调用didEnterRegion,因此当两次输入区域时我只希望它输入一次.我怎能避免这种情况?
谢谢你的帮助.
解
解决方案真的很简单,我只是以错误的方式去做.我必须选择使用2个方法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 }
解决方法
另一种方法是在开始监视区域时测试区域内的位置.这个解决方案听起来不是那么简单:你需要先通过调用startUpdatingLocation更新当前位置,因为只读取locationManager的location属性可能会给你陈旧或极不准确的读数.