区域监控当前位置在退出时不通知

Ida*_*she 12 objective-c core-location cllocationmanager ios clregion

我正在尝试测试区域监控,因为我正在获得这样的当前位置:

- (void)startLocationTracking
{
    CLLocationManager *locationManager = [[CLLocationManager alloc] init];

    // Start location manager
    if ([CLLocationManager locationServicesEnabled] && [CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorized) {
        locationManager = [LocationTracker sharedLocationManager];
        locationManager.delegate = self;
        [locationManager startMonitoringSignificantLocationChanges];
    }
}
Run Code Online (Sandbox Code Playgroud)

并跟踪区域监控的第一个位置,如下所示:

-(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);
    });
}
Run Code Online (Sandbox Code Playgroud)

然后在当前区域的每个出口处,我正在监视新位置,如下所示:

- (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];
}
Run Code Online (Sandbox Code Playgroud)

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

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

这不会发生.

哪里我错了?

我尝试使用'Freeway Drive'模拟器.

更新:

经过测试和工作,由于地理围栏中的Apple漏洞,应用程序仅支持7.1+,非常糟糕,但我没有其他想法.

Ric*_*cky 11

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

原因如下: -

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

    要解决此问题:您应该使用在应用程序的整个生命周期中共享 的单例 .locationManagerlocationManager

  2. 我相信你不应该startMonitoringForRegion在委托方法中-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:.原因是,如果你再调用startLocationTracking一次,会有多个locationManager.多个locationManagers可以监视可能导致多个通知的同一区域.

  3. 致电后[manager startMonitoringForRegion:region];,不会立即监控该地区.如果您不相信我,请尝试以下代码: -

    [locationManager startMonitoringForRegion:region];
    NSLog(@"%@",locationManager.monitoredRegions);
    
    Run Code Online (Sandbox Code Playgroud)

您会发现您刚监控的区域不在内部locationManager.monitoredRegions.由于这是在iOS级别上处理的,因此,我认为可能需要几分钟时间才能对该区域进行监控.

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

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

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

在iOS 6中,半径在1到400米之间的区域在iPhone 4S或更高版本的设备上运行得更好.(在iOS 5中,半径在1到150米之间的区域在iPhone 4S和更高版本的设备上运行得更好.)在这些设备上,应用程序可以在3到5分钟内平均接收输入的适当区域或区域退出通知,如果不是更快.

注意:只要设备从之前的通知移动500米或更长时间,应用就会收到通知.它不应该比每五分钟更频繁地预期通知.如果设备能够从网络检索数据,则位置管理器更有可能及时发送通知.

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

有关Singleton LocationManager的更多信息,您可以查看以下答案:背景位置服务在iOS 7中不起作用.GitHub上有一个完整的项目,它包含一个Singleton LocationManager类,我将其命名为LocationTracker.

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