【问题标题】:iOS 7 CoreLocation: region monitoring fails on the first time after location services are authorisediOS 7 CoreLocation:位置服务授权后区域监控首次失败
【发布时间】:2014-04-19 17:19:30
【问题描述】:

我在使用 CoreLocation 的应用上发现了一个奇怪的行为。我正在使用区域监控功能,但是在授权定位服务(通过弹出窗口或设置->定位服务)后,区域监控失败(操作无法完成。kCLErrorDomain 错误 5.)。如果我关闭应用程序并重新启动(因此已经授权),一切都会按预期工作。 我的代码如下所示:

-(void)initializeLocationServices
{
    NSLog(@"Started location services");

    locationManager = [[CLLocationManager alloc] init];
    locationManager.delegate = self;
    locationManager.distanceFilter = kCLDistanceFilterNone;
    locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
    locationManager.pausesLocationUpdatesAutomatically = NO;

    [locationManager startUpdatingLocation]; // to show authorisation popup
}

-(CLCircularRegion*)createRegion
{   
    // Test coordinates
    CLLocationDegrees latitude = 50;
    CLLocationDegrees longitude = -1;
    CLLocationDistance radius = 50; // meters;

    // If radius is too large, registration fails automatically, so limit the radius to the maximum value
    if (radius > locationManager.maximumRegionMonitoringDistance) {
        radius = locationManager.maximumRegionMonitoringDistance;
    }

    CLCircularRegion* region = [[CLCircularRegion alloc] initWithCenter:CLLocationCoordinate2DMake(latitude, longitude) radius:radius identifier:@"TEST"];

    region.notifyOnEntry = YES;
    region.notifyOnExit = YES;

    NSLog(@"Created region");

    return region;
}

-(void)monitorProximity
{
    CLRegion *region = [self createRegion];

    // Check if support is unavailable
    if ( ![CLLocationManager isMonitoringAvailableForClass:[CLRegion class]]) {
        NSLog( @"Failed to initialise region monitoring: support unavailable");
        return;
    }

    // Check if authorised
    if ([CLLocationManager authorizationStatus] != kCLAuthorizationStatusAuthorized) {
        NSLog( @"Failed to initialise region monitoring: app not authorized to use location services");
        return;
    } else {
        NSLog(@"Started monitoring proximity");
    }


    // Clear out any old regions to prevent buildup.
    if ([locationManager.monitoredRegions count] > 0) {
        for (id obj in locationManager.monitoredRegions)
            [locationManager stopMonitoringForRegion:obj];
    }

    [locationManager startMonitoringForRegion:region];
}

-(void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region
{
    NSLog(@"Started monitoring for region: %@", [region description]);
    [locationManager requestStateForRegion:region]; // check if already inside region
}

-(void)locationManager:(CLLocationManager *)manager monitoringDidFailForRegion:(CLRegion *)region withError:(NSError *)error
{
    NSLog(@"Failed to start monitoring for region: %@", [error localizedDescription]);
}


-(void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region
{
    NSLog(@"didDetermineState");

    if (state == CLRegionStateInside) {

        NSLog(@"inside");
        return;


    } else if (state == CLRegionStateOutside) {
        NSLog(@"outside");

    } else {
        NSLog(@"unknown");
    }

}

-(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{
    NSLog(@"didEnterRegion");
}

-(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
{
    NSLog(@"didExitRegion");
}

-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
    NSLog(@"Monitoring authorisation status is now: %@", status == kCLAuthorizationStatusAuthorized ? @"authorized" : @"not authorized");

    if (status == kCLAuthorizationStatusAuthorized) {
        [self monitorProximity];
    }
}

我在这里做错了吗?调用 didChangeAuthorizationStatus 后流程是否有问题?

【问题讨论】:

    标签: ios objective-c ios7 core-location region-monitoring


    【解决方案1】:

    kCLErrorDomain 5 是一个含义广泛的概念。

    其中一个来源是当您致电[locationManager requestStateForRegion:region] 时,当您第一次监控某个区域以了解您是否已经在该区域时,这是必要的。这是因为 didEnter 区域只有在您实际进入该区域时才会被调用。通常这意味着您第一次监视该区域时,您必须等待 5 秒钟,直到未检测到该区域,然后才会在您下次进入该区域时触发 didEnter region。

    关于问题的原因有很多不同的报告:

    但是,这些都不适合我。我认为我的根本原因类似于 iOS 7.1 错误,它只是在某些设备上随机停止工作。我尝试了重新启动和重新启动蓝牙,没有任何帮助。

    不知道发生了什么变化,但我第二天又试了一次,它开始工作了。

    基本上,您可能想尝试其他设备,直到该设备再次开始工作。

    【讨论】:

      【解决方案2】:

      other user reports 看来,kCLErrorDomain 5 似乎是区域监控失败的“包罗万象”;它没有提供太多有用的信息。我相信你的问题是由线路引起的

      [locationManager requestStateForRegion:region]; // check if already inside region
      

      你从委托方法didStartMonitoringForRegion:内部调用的

      我在自己的项目中看到了一些非常相似的东西,将这条线去掉(或延迟执行一段时间)解决了这个问题。我最好的猜测是,当这个委托方法触发时,iOS 仍在运行一些内部区域监控代码,所以现在不是调用 requestStateForRegion:

      的合适时间

      试着把它拿出来看看是不是答案。

      【讨论】:

      • 一个简单的方法是使用 NSTimer,
        例如NSTimer scheduledTimerWithTimeInterval:30.0f target:self selector:@selector(delayMethod) userInfo:nil repeats:NO];我测试了17个区域,效果很好,在延迟方法中加入如下
        [locationManager requestStateForRegion:region];
      【解决方案3】:

      kCLErrorDomain 代码/错误 5 表示您已尝试监控超过 20 个 CLRegions。 说明here

      startMonitoringForRegion描述它说:
      一个应用程序一次最多可以注册 20 个区域。为了及时报告区域变化,区域监控服务需要网络连接。

      【讨论】:

      • 最奇怪的部分是我只尝试监控一个区域,而我的代码只执行一次(didChangeAuthorizationStatus -> monitorProximity -> startMonitoringForRegion)。是否有可能在其他情况下得到 kCLErrorDomain 错误 5?我的流程在某些方面有问题吗?
      • 我也看到这个只有一个 CLBeaconRegion。
      • 我觉得这个答案充其量是可疑的。在它正常工作数周后,我遇到了这个问题。在monitoringDidFailForRegion里面的xcode中检查po manager.monitoredRegions,它只列出了一个区域。
      猜你喜欢
      • 1970-01-01
      • 2013-07-04
      • 1970-01-01
      • 2014-08-09
      • 2013-06-07
      • 2013-11-20
      • 2014-05-23
      • 2013-02-03
      • 2020-12-07
      相关资源
      最近更新 更多