iOS 7 CoreLocation: мониторинг региона не выполняется в первый раз после авторизации служб определения местоположения

Я обнаружил странное поведение в своем приложении с помощью 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?

3 ответа

Из других отчетов пользователей кажется, что kCLErrorDomain 5 является "ловить все" для мониторинга региона не удается; это не дает много полезной информации. Я считаю, что ваша проблема вызвана линией

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

который вы вызываете изнутри метода делегата didStartMonitoringForRegion:

Я видел нечто очень похожее в моем собственном проекте, и удаление этой строки (или задержка ее выполнения на некоторое время) решило проблему. Мое лучшее предположение состоит в том, что iOS все еще выполняет некоторый код мониторинга внутренней области, когда этот метод делегата запускается, так что это не подходящее время для вызова requestStateForRegion:

Попробуйте убрать это и посмотреть, если это ответ.

Код / ошибка 5 kCLErrorDomain означает, что вы пытались отслеживать более 20 регионов CLRegions. Описание здесь

смотрите описание startMonitoringForRegion
Приложение может зарегистрировать до 20 регионов одновременно. Чтобы своевременно сообщать об изменениях в регионе, службе мониторинга региона требуется подключение к сети.

kCLErrorDomain5 Поймать все, что может означать много разных вещей.

Один из источников, когда вы звоните [locationManager requestStateForRegion:region] что необходимо, когда вы впервые наблюдаете за регионом, чтобы узнать, находитесь ли вы уже в регионе или нет. Это связано с тем, что регион didEnter будет вызываться только тогда, когда вы действительно введете регион. Обычно это означает, что при первом мониторинге региона вы должны подождать 5 секунд, пока регион не будет обнаружен, и только после этого будет запущен регион В следующий раз, когда вы находитесь в регионе.

Есть много разных сообщений о причинах проблемы:

Однако все это не помогло мне. Я думаю, что моя основная причина была похожа на ошибку iOS 7.1, когда она просто случайно перестала работать на некоторых устройствах. Я попробовал перезагрузить и перезагрузить блютуз, ничего не помогло.

Не уверен, что изменилось, но я только попробовал снова на следующий день, и это начало работать.

В принципе, вы можете попробовать другое устройство, пока оно не начнет работать снова.

Другие вопросы по тегам