区域监视当前位置不会退出时通知

我试图testing区域监控,因为我得到这样的当前位置:

- (void)startLocationTracking { CLLocationManager *locationManager = [[CLLocationManager alloc] init]; // Start location manager if ([CLLocationManager locationServicesEnabled] && [CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorized) { locationManager = [LocationTracker sharedLocationManager]; locationManager.delegate = self; [locationManager startMonitoringSignificantLocationChanges]; } } 

跟踪像这样的区域监视的第一个位置:

 -(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ CLRegion *region = [[CLRegion alloc] initCircularRegionWithCenter:manager.location.coordinate radius:300 identifier:@"first location initializer"]; NSLog(@"0: %@", manager.location); NSLog(@"1: %@", region); [manager startMonitoringForRegion:region]; NSLog(@"[locationManager startMonitoringForRegion:%@];", region); }); } 

然后在当前区域的每个退出中,我都会监视新的位置,如下所示:

 - (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region { NSLog(@"%s, %@", __PRETTY_FUNCTION__, region); } - (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region { NSLog(@"%s, %@", __PRETTY_FUNCTION__, region); NSArray *allRegions = manager.monitoredRegions.allObjects; if (allRegions.count > 0) { for (CLRegion *reg in allRegions) { [manager stopMonitoringForRegion:reg]; } } CLLocationCoordinate2D cord = CLLocationCoordinate2DMake(manager.location.coordinate.latitude, manager.location.coordinate.longitude); CLRegion *regionNew = [[CLRegion alloc] initCircularRegionWithCenter:cord radius:300 identifier:@"new region"]; NSLog(@"region: %@", region); NSLog(@"regionNew: %@", regionNew); [manager startMonitoringForRegion:regionNew]; } 

我会解释我期望发生的事情:

  1. 在区域监控中注册当前位置。
  2. 通知用户出口当前区域。
  3. 在退出日志中,再次将当前位置注册为区域。

这不会发生。

我哪里错了?

我在模拟器上尝试了'Freeway Drive'。

更新:

testing和工作,由于苹果在geofencing的bug,应用程序将只支持7.1 +,很糟糕,但我没有另一个想法。

我认为你实施区域监控的方式可能会导致一些问题。

原因如下:

  1. startLocationTracking方法内部,您的locationManager是一个本地对象,它不会延伸到该方法的生命周期。 这也意味着每次调用startLocationTracking ,都会有一个新的locationManager对象被分配一个新的内存块。

    为了解决这个问题:你应该在应用程序的整个生命周期中使用一个单独的 locationManager ,它是一个共享的locationManager

  2. 相信你不应该在委托方法里面启动startMonitoringForRegion -(void)locationManager:(CLLocationManager *)manager didUpdateLocations: 原因是,如果您多调用一次startLocationTracking ,则会有多个locationManager。 多个位置pipe理员可以监视可能导致多个通知的相同区域。

  3. 你调用[manager startMonitoringForRegion:region]; ,该地区将不会立即受到监控。 如果你不相信我,请尝试下面的代码:

     [locationManager startMonitoringForRegion:region]; NSLog(@"%@",locationManager.monitoredRegions); 

你会发现你刚刚监测的区域不在locationManager.monitoredRegions 。 由于这是在iOS级别上处理的,所以我认为可能需要几分钟的时间才能对该地区进行监控。

您还应该了解iOS中区域监控的其他限制: –

https://developer.apple.com/library/mac/documentation/CoreLocation/Reference/CLLocationManager_Class/CLLocationManager/CLLocationManager.html

一个应用程序一次最多可以注册20个区域。 为了及时报告地区变化,地区监测服务需要networking连接。

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

注意:只要设备从先前的通知移动500米或更远,应用程序就会收到通知。 它不应该比每五分钟一次更频繁地发出通知。 如果设备能够从networking中检索数据,则位置pipe理者更可能及时地发送通知。

我不知道你的应用程序是什么,我相信你应该重新devise你的应用程序的stream程。 您应该尝试监视委托方法之外的区域。

有关Singleton LocationManager的更多信息,你可以看看这个答案: 背景定位服务不适用于iOS 7 。 GitHub上有一个完整的项目,它包含一个我命名为LocationTrackerSingleton LocationManager类

您可能还想查看一下我在一个月前发现的iOS 7中的区域监视故障(通过解决方法来解决小故障): iOS 7上的区域监视故障- 多个通知同时发生

对于代表方法(didEnterRegion和didExitRegion)没有被调用的最满意的答案是,苹果文档说,在进入或退出3到5分钟后会通知你,但在实际testing中,我发现你必须等待大约7至8分钟。

我testing了10到15次,我的区域半径在80米左右。 我正在挠头,看看出了什么问题。 我离开模拟器打开位置跟踪(使用gpx文件进行位置模拟)。 8分钟后,didExitRegion被调用。

另外,如果您想在后台执行此操作,则必须在目标上启用背景模式。 在这里输入图像说明