iOS 7 CoreLocation:在授权位置服务后,区域监控首次失败 [英] iOS 7 CoreLocation: region monitoring fails on the first time after location services are authorised

查看:129
本文介绍了iOS 7 CoreLocation:在授权位置服务后,区域监控首次失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I identified a strange behaviour on my app using CoreLocation. I'm using the region monitoring functionality but, after authorising the location services (via popup or settings->Location Services) region monitoring fails (The operation couldn’t be completed. kCLErrorDomain error 5.). If I close the app and restart (therefore already authorised) everything works as expected. My code looks like this:

-(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后,我的流程有问题吗?

Am I doing something wrong here? Do I have problems with the flow after didChangeAuthorizationStatus gets called?

推荐答案

来自其他用户报告,似乎 kCLErrorDomain 5 是区域监控失败的'catch all' ;它没有提供太多有用的信息。我相信你的问题是由行造成的

From other user reports, it seems that kCLErrorDomain 5 is a 'catch all' for region monitoring fails; it doesn't provide much useful information. I believe that your issue is being caused by the line

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

您在委托方法中调用 didStartMonitoringForRegion:

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

I saw something very similar in my own project and taking this line out (or delaying its execution for a while) solved the issue. My best guess is that iOS is still doing running some internal region monitoring code when this delegate method fires, so it's not an appropriate time to call requestStateForRegion:

尝试解决这个问题,看看答案是否正确。

Try taking this out and see if it is the answer.

这篇关于iOS 7 CoreLocation:在授权位置服务后,区域监控首次失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆