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 регионов одновременно. Чтобы своевременно сообщать об изменениях в регионе, службе мониторинга региона требуется подключение к сети.
kCLErrorDomain
5
Поймать все, что может означать много разных вещей.
Один из источников, когда вы звоните [locationManager requestStateForRegion:region]
что необходимо, когда вы впервые наблюдаете за регионом, чтобы узнать, находитесь ли вы уже в регионе или нет. Это связано с тем, что регион didEnter будет вызываться только тогда, когда вы действительно введете регион. Обычно это означает, что при первом мониторинге региона вы должны подождать 5 секунд, пока регион не будет обнаружен, и только после этого будет запущен регион В следующий раз, когда вы находитесь в регионе.
Есть много разных сообщений о причинах проблемы:
- Убедитесь, что ведется мониторинг не более 20 маяков
5
означает "RegionMonitoringFailure". Убедитесь, что радиус не слишком большой (не относится к мониторингу маяка).- Убедитесь, что обновления местоположения зарегистрированы
- Пропустить вызов requestStateForRegion, однако я описал выше, почему это необходимо сделать.
- Перезапуск устройства и Bluetooth может помочь
- Попробуйте с 30 секундной задержкой
Однако все это не помогло мне. Я думаю, что моя основная причина была похожа на ошибку iOS 7.1, когда она просто случайно перестала работать на некоторых устройствах. Я попробовал перезагрузить и перезагрузить блютуз, ничего не помогло.
Не уверен, что изменилось, но я только попробовал снова на следующий день, и это начало работать.
В принципе, вы можете попробовать другое устройство, пока оно не начнет работать снова.