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

Я обнаружил странное поведение в своем приложении с помощью CoreLocation. Я использую функцию мониторинга региона, но после авторизации служб определения местоположения (через всплывающее окно или настройки-> Службы определения местоположения) происходит сбой мониторинга региона (Операция не может быть завершена. kCLErrorDomain error 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?


person Rui    schedule 14.03.2014    source источник


Ответы (3)


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

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

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

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

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

person Carlos P    schedule 01.09.2014
comment
простой способ - использовать NSTimer, ‹br/› например. NSTimer scheduledTimerWithTimeInterval:30.0f target:self selector:@selector(delayMethod) userInfo:nil repeats:NO]; Я тестировал с 17 регионами, и это работает, поместите следующий метод задержки‹br/› [locationManager requestStateForRegion:region]; - person windsound; 24.06.2015

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

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

person Kostiantyn Koval    schedule 14.03.2014
comment
Самое странное, что я пытаюсь отслеживать только одну зону, и мой код выполняется только один раз (didChangeAuthorizationStatus -> monitorProximity -> startMonitoringForRegion). Можно ли получить ошибку kCLErrorDomain 5 в других ситуациях? Мой поток в чем-то неверен? - person Rui; 14.03.2014
comment
Я также вижу это только с одним CLBeaconRegion. - person chadum; 17.04.2014
comment
Я нахожу этот ответ в лучшем случае сомнительным. Я испытываю эту проблему после того, как она работала нормально в течение нескольких недель. Проверка po manager.monitoredRegions в xcode внутри monitoringDidFailForRegion показывает только один регион. - person Mike Caron; 20.05.2014

kCLErrorDomain 5 — это все, что может означать много разных вещей.

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

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

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

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

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

person Senseful    schedule 21.08.2018