iOS requestStateForRegion 在 didStartMonitoringFor 之后返回 .unknown
iOS requestStateForRegion returning .unknown after didStartMonitoringFor
对为什么我的 AppDelegate CLLocationManager 有时无法成功确定 CLRegionState (CLRegionState.unknown) 感到困惑,即使我确保在 didStartMonitoringForRegion
之前不会调用 requestStateForRegion
。似乎是某种竞争条件,我不明白我是如何处理的。
相关,得到CLRegionState.unknown后怎么办?一直请求状态直到我得到什么? (这看起来很糟糕)
AppDelegate:
- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
self.locationManager = [[CLLocationManager alloc] init];
[self.locationManager setDelegate:self];
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
- (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(nonnull CLRegion *)region {
NSLog(@"%@", [NSString stringWithFormat:@"didStartMonitoringFor region with ID: %@", region.identifier]);
// delay per
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void) {
[self.locationManager requestStateForRegion:region];
});
}
- (void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(nonnull CLRegion *)region {
NSLog(@"%@", [NSString stringWithFormat:@"didDetermineState from AppDelegate CLLocationManager: %@ (%ld)", region.identifier, (long)state ]);
NSString *baseUrl = [self fetchBaseUrl];
switch (state) {
case CLRegionStateInside:
NSLog(@"%@", @"Determined .inside state for geofence");
[HelperFunctions postGeofenceTransitionWithBaseUrl:baseUrl region:region transitionType:1];
break;
default:
break;
}
}
抄袭日志:
Adding geofence with ID: 5:90fd74e0-cbc7-dbe5-20fc-b870203055e1
Adding geofence with ID: 8:d408f466-ea1b-6cbb-382f-f7567db61157
Adding geofence with ID: 7:ba97dda2-39a7-9b95-8ea9-ea183d69a858
didStartMonitoringFor region with ID: 5:90fd74e0-cbc7-dbe5-20fc-b870203055e1
didStartMonitoringFor region with ID: 8:d408f466-ea1b-6cbb-382f-f7567db61157
didStartMonitoringFor region with ID: 7:ba97dda2-39a7-9b95-8ea9-ea183d69a858
didDetermineState from AppDelegate CLLocationManager: 5:90fd74e0-cbc7-dbe5-20fc-b870203055e1 (0)
didDetermineState from AppDelegate CLLocationManager: 8:d408f466-ea1b-6cbb-382f-f7567db61157 (0)
didDetermineState from AppDelegate CLLocationManager: 7:ba97dda2-39a7-9b95-8ea9-ea183d69a858 (0)
谢谢
这是因为你在块中使用了入口参数region
,而没有将其设为块变量。
在- (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(nonnull CLRegion *)region {
中添加:
__block CLRegion *blockRegion = region;
并在块内使用 blockRegion
。
当你想使用 requestStateForRegion 时要小心。此方法可能会针对设备的 currentLocation 生成不正确的结果。当我使用不同的网络进行一些实验时,如果您使用的是 LTE,它会丢失某些区域的某些状态,而在 WIFI 上,我看到它会产生重复的计数器事件,例如对于位置 A,它会同时产生进入和退出。
我仔细阅读了苹果文档下对这个方法的评论
Asynchronously retrieve the cached state of the specified region.
此缓存状态不准确。
对为什么我的 AppDelegate CLLocationManager 有时无法成功确定 CLRegionState (CLRegionState.unknown) 感到困惑,即使我确保在 didStartMonitoringForRegion
之前不会调用 requestStateForRegion
。似乎是某种竞争条件,我不明白我是如何处理的。
相关,得到CLRegionState.unknown后怎么办?一直请求状态直到我得到什么? (这看起来很糟糕)
AppDelegate:
- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
self.locationManager = [[CLLocationManager alloc] init];
[self.locationManager setDelegate:self];
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
- (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(nonnull CLRegion *)region {
NSLog(@"%@", [NSString stringWithFormat:@"didStartMonitoringFor region with ID: %@", region.identifier]);
// delay per
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void) {
[self.locationManager requestStateForRegion:region];
});
}
- (void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(nonnull CLRegion *)region {
NSLog(@"%@", [NSString stringWithFormat:@"didDetermineState from AppDelegate CLLocationManager: %@ (%ld)", region.identifier, (long)state ]);
NSString *baseUrl = [self fetchBaseUrl];
switch (state) {
case CLRegionStateInside:
NSLog(@"%@", @"Determined .inside state for geofence");
[HelperFunctions postGeofenceTransitionWithBaseUrl:baseUrl region:region transitionType:1];
break;
default:
break;
}
}
抄袭日志:
Adding geofence with ID: 5:90fd74e0-cbc7-dbe5-20fc-b870203055e1
Adding geofence with ID: 8:d408f466-ea1b-6cbb-382f-f7567db61157
Adding geofence with ID: 7:ba97dda2-39a7-9b95-8ea9-ea183d69a858
didStartMonitoringFor region with ID: 5:90fd74e0-cbc7-dbe5-20fc-b870203055e1
didStartMonitoringFor region with ID: 8:d408f466-ea1b-6cbb-382f-f7567db61157
didStartMonitoringFor region with ID: 7:ba97dda2-39a7-9b95-8ea9-ea183d69a858
didDetermineState from AppDelegate CLLocationManager: 5:90fd74e0-cbc7-dbe5-20fc-b870203055e1 (0)
didDetermineState from AppDelegate CLLocationManager: 8:d408f466-ea1b-6cbb-382f-f7567db61157 (0)
didDetermineState from AppDelegate CLLocationManager: 7:ba97dda2-39a7-9b95-8ea9-ea183d69a858 (0)
谢谢
这是因为你在块中使用了入口参数region
,而没有将其设为块变量。
在- (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(nonnull CLRegion *)region {
中添加:
__block CLRegion *blockRegion = region;
并在块内使用 blockRegion
。
当你想使用 requestStateForRegion 时要小心。此方法可能会针对设备的 currentLocation 生成不正确的结果。当我使用不同的网络进行一些实验时,如果您使用的是 LTE,它会丢失某些区域的某些状态,而在 WIFI 上,我看到它会产生重复的计数器事件,例如对于位置 A,它会同时产生进入和退出。 我仔细阅读了苹果文档下对这个方法的评论
Asynchronously retrieve the cached state of the specified region.
此缓存状态不准确。