Вопрос:

StartUpdateLocations в фоновом режиме, didUpdatingToLocation вызывается только 10-20 раз

ios objective-c iphone core-location cllocationmanager

3688 просмотра

3 ответа

94 Репутация автора

Тестирующее устройство: iPhone 5 (iOS 7)

У меня есть приложение, которое использует RegionMonitoringи updateLocation. Если введен регион, didEnterRegionон называется ожидаемым. Тогда я звоню startUpdatingLocation. Но метод didUpdateToLocationвызывается только 10-20 раз, в то время как он должен обновлять местоположение, пока не сработает таймер.

Соответствующий код:

CLLocationManager *_locationManager;
NSTimer *_timer;

-(void)initLocationManager 
{
    _locationManager = [[CLLocationManager alloc] init];
    _locationManager.delegate = self;
    [_locationManager setActivityType:CLActivityTypeOther];
    [_locationManager setDesiredAccuracy:kCLLocationAccuracyBestForNavigation];
    [_locationManager setPausesLocationUpdatesAutomatically:NO];
    [_locationManager setDistanceFilter:kCLDistanceFilterNone];
}


//Did Enter Region, called as expected:
- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{
    [_locationManager startUpdatingLocation];
    _timer = [NSTimer scheduledTimerWithTimeInterval:300.0f target:self selector:@selector(scheduleMethod:) userInfo:nil repeats:NO];
}


//Timer Fire Method:
- (void) scheduleMethod:(NSTimer*)timer
{
    [Utils writeToLog:@"Timer-Stop"];
    [_locationManager stopUpdatingLocation];
}


//This Method only called 10-20 Times (in the first 10-20 Seconds) and not the complete 5 Minutes:
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
     [Utils writeToLog:@"LocationUpdate!"];
}

До сих пор я пытался: перезапустить обновления в locationManagerDidPauseLocationUpdatesметоде, но кажется, что это никогда не будет вызвано:

-(void)locationManagerDidPauseLocationUpdates:(CLLocationManager *)manager
{
    [WRUtils writeToLog:@"LocationUpdate paused, restarted"];
    [_locationManager startUpdatingLocation];
}

Проверьте наличие ошибок в didFailWithErrorметоде, но это также не вызывается. И немного поиграл со свойствами:

[_locationManager setActivityType:CLActivityTypeOther];
[_locationManager setDesiredAccuracy:kCLLocationAccuracyBestForNavigation];
[_locationManager setPausesLocationUpdatesAutomatically:NO];

Настройки Plist верны, я думаю: Требуемые режимы фона ДА Требуемые режимы фона Элемент 0 Приложение регистрирует обновления местоположения

Как я могу решить это?

Автор: flo Источник Размещён: 25.11.2013 08:23

Ответы (3)


0 плюса

424 Репутация автора

В фоновом режиме таймер не будет работать, поэтому здесь ваш объект таймера не будет отвечать, вам нужно создать обработчик фоновых задач, проверить комментарий по ссылке ниже,

Как запустить таймер в фоновом режиме приложения?

В фоновом режиме, если вы хотите продолжить службу определения местоположения, вам нужно установить флаг pausesLocationUpdatesAutomatics, пометить информацию о

pausesLocationUpdatesАвтоматически помечает информацию

  if ([self.locationManager respondsToSelector:@selector(pausesLocationUpdatesAutomatically)]) {
  self.locationManager.pausesLocationUpdatesAutomatically = NO;
  }

проверьте мой комментарий о том, что служба определения местоположения переходит в состояние «Неактивно» в iPhone 5

Для диспетчера местоположения ниже есть методы CLLocationManagerDelegate для обновления местоположения,

   - (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
       fromLocation:(CLLocation *)oldLocation [Deprecated in __IPHONE_6_0]

  - (void)locationManager:(CLLocationManager *)manager
 didUpdateLocations:(NSArray *)locations __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_6_0);

Где вы нашли

  - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation ??
Автор: Vishwa Patel Размещён: 25.11.2013 08:26

25 плюса

1431 Репутация автора

Решение

Apple представила новую политику в iOS 7. iOS 7 больше не доставляет обновления местоположения в фоновом режиме, если вы вызываете «startUpdatingLocation», когда приложение находится в фоновом режиме. В этом случае вы получите обновление только тогда, когда приложение выведено на передний план.

Когда вы используете функцию геозоны, ваше приложение просто получает несколько секунд каждый раз, когда вы получаете уведомление RegionEntered / Exited для обработки этого уведомления. И в эти несколько секунд вы также можете получать обновления местоположения. После того, как эти несколько секунд закончились, iOS 7 просто снова приостанавливает ваше приложение.

Вы можете использовать фоновое задание, чтобы получить больше, чем несколько секунд, но в iOS 7 Apple также сократила время, в течение которого приложения могут работать в фоновом режиме, с 10 минут (iOS 6 и старше) до всего 3 минут под iOS 7. Похоже, что эти 3 минуты - общая сумма за все время, пока приложение находится в фоновом режиме. Это означает, что вы не можете попросить iOS 7 10 раз, чтобы получить 1 минуту фонового времени, вы получите всего 3 минуты, поэтому после третьего раза, когда вы попросили минуту, ваше приложение больше не будет иметь фонового времени. вообще.

Единственный шанс получить обновления местоположения в фоновом режиме - вызвать «startUpdatingLocation», пока приложение находится на переднем плане. Это печально, особенно когда вам нужны обновления местоположения только в ответ на сообщения Region (Enter / Exit), потому что вам нужно постоянно запускать обновления местоположения. Но вы можете по крайней мере уменьшить использование батареи, установив значение точности в kCLLocationAccuracyThreeKilmeters, когда вам не нужно обновлять местоположение и устанавливать точность kCLLocationAccuracyBest только тогда, когда вам действительно нужны географические координаты. iOS не включает GPS для значения kCLLocationAccuracyThreeKilmeters, поэтому в этом случае использование батареи будет умеренным.

Также значение kCLLocationAccuracyBestForNavigation для точности, кажется, вызывает проблемы под IOS 7. Я не получаю никаких обновлений местоположения с этим значением, если устройство не подключено к внешнему источнику питания.

В целом новая политика iOS 7 для обновлений местоположения значительно усложняет разработку определенных видов приложений. Вместо того, чтобы регистрироваться для получения обновлений местоположения только при необходимости, вы вынуждены регистрироваться на них в течение всего времени существования вашего приложения. Что, конечно, разряжает батарею немного быстрее, хотя намерение Apple в этой новой политике, вероятно, было противоположным.

ОБНОВИТЬ:

После еще нескольких испытаний я нашел какое-то решение проблемы. В документах Apple упоминается, что при использовании API значительного изменения местоположения приложения могут получать обновления местоположения в фоновом режиме, даже если в фоновом режиме запущено «startUpdatingLocation».

Мои первые тесты не сработали. Я регистрировал свое приложение для значительных обновлений местоположения в методах делегатов мониторинга региона непосредственно перед вызовом startUpdatingLocation (так что эта служба местоположения включается только при необходимости), но это по-прежнему не доставляет обновления местоположения в фоновом режиме, как предполагается в документации.

Но если вы начинаете прослушивать значительные изменения местоположения сразу после запуска приложения (и никогда не выключаете его), вы можете вызвать start startUpdatingLocation, пока приложение находится в фоновом режиме, а также получать обновления местоположения в фоновом режиме. Использование батареи при наличии функции «значительного изменения местоположения» все время кажется очень низким, так что это, вероятно, будет решением для большинства приложений.

Вы должны проверить, доступна ли функция «значительного изменения местоположения» на устройстве, но кажется, что все современные устройства поддерживают это. Даже 5-е поколение iPod Touch поддерживает его (iPod Touch не может использовать вышки сотовой связи для обновления местоположения, что является базовым методом этой функции в соответствии с документами Apple, поэтому я предполагаю, что мы можем предположить, что все текущие устройства, работающие на iOS 7 может использовать API «значительное обновление местоположения». Хотя, возможно, неплохо проверить, действительно ли эта функция доступна, возможно, существуют определенные обстоятельства, когда эта функция недоступна).

Использование API «значительного изменения местоположения» может иметь один недостаток: приложение можно запускать в фоновом режиме (если оно было прекращено в фоновом режиме iOS для повторного использования памяти для других приложений) многократно и без необходимости всякий раз, когда устройство «значительно перемещается». «(Согласно документам: когда сотовая вышка менялась, но не чаще, чем раз в 5 минут). Таким образом, будут запущены приложения, которые нужно активировать только при выходе или входе из определенного региона, и сообщат об изменении местоположения все время, не только в этих регионах. Но я полагаю, что это должно быть намного лучше, чем постоянное обновление стандартных местоположений.

Мой iPhone 5s разряжает батарею только на 1% за ночь при активных значительных изменениях местоположения, а не на 12% при наличии стандартных обновлений местоположения с точностью до 3 км.

Надеюсь, что это поможет всем разработчикам, которые борются с новым поведением iOS 7.

Автор: Alex Размещён: 10.12.2013 07:36

0 плюса

2902 Репутация автора

Используйте код ниже в вашем didEnterRegionметоде, чтобы начать обновления снова

[_locationManager startMonitoringSignificantLocationChanges];
if ([_locationManager respondsToSelector:@selector(setAllowsBackgroundLocationUpdates:)])
{
    _locationManager.allowsBackgroundLocationUpdates =YES;

}
[_locationManager startUpdatingLocation];
Автор: Desert Rose Размещён: 15.04.2016 07:46
Вопросы из категории :
32x32