iOS Не типичная проблема таймера фонового отслеживания местоположения

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

Моя идея состояла в том, что каждые x минут служба запускается, и когда она имеет правильное новое местоположение, она снова освобождается, теперь для тестирования устанавливается значение 10 секунд. (Значительное LocationChange не сработало, недостаточно обвинено)

Я много искал (iOS Dev center + Stackru) и нашел "новые" функции определения местоположения фона, которые позволяют запускать код в течение 10 минут после перехода к фону, используя beginBackgroundTaskWithExpirationHandler, несколько блоков и таймер.

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

код работает "отлично", но:

  • Таймер иногда срабатывает, иногда нет.
  • Когда таймер срабатывает, это займет минимум 10 минут.
  • Некоторые случайные действия в ОС (например, вход на рабочий стол поиска), по-видимому, стимулируют срабатывание таймера (не уверен в этом, я не понимаю, как это возможно, но это так...)

И через код будет еще один вопрос.

методы appdelegates:

//applicationDidEnterBackground

- (void)applicationDidEnterBackground:(UIApplication *)application{

NSLog(@"to background");

UIApplication*    app = [UIApplication sharedApplication];

bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
    [app endBackgroundTask:bgTask];
    bgTask = UIBackgroundTaskInvalid;
}];

// Start the long-running task and return immediately.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    // Do the work associated with the task.
    _triggertimer = nil;
    [self initTimer];

});
NSLog(@"backgroundTimeRemaining: %.0f", [[UIApplication sharedApplication] backgroundTimeRemaining]);}

//initTimer

- (void) initTimer{
NSLog(@"InitTimer ");


UIApplication *app = [UIApplication sharedApplication];

bgTask = [app beginBackgroundTaskWithExpirationHandler:^{



_triggertimer = [NSTimer scheduledTimerWithTimeInterval:10.0
                                                     target:self
                                                   selector:@selector(checkUpdates:)
                                                   userInfo:nil
                                                    repeats:YES];

[[NSRunLoop currentRunLoop] addTimer:_triggertimer forMode:NSDefaultRunLoopMode] ;
[[NSRunLoop currentRunLoop] run];

}];}

//checkUpdates

- (void)checkUpdates:(NSTimer *)timer{

NSLog(@"CheckUpdates ");

UIApplication*    app = [UIApplication sharedApplication];

if (nil == _locationManager) _locationManager = [[CLLocationManager alloc] init];

_locationManager.delegate = self;


_locationManager.distanceFilter = 10;
_locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;

[_locationManager startUpdatingLocation];
[_locationManager startMonitoringSignificantLocationChanges];



double remaining = app.backgroundTimeRemaining;
NSLog(@"Reminaing %f", remaining);}

Я пытался многое исправить, и, может быть, я что-то напутал или пропустил... Что ты видишь? возможно некоторые концептуальные ошибки, я пытаюсь представить себя блокам, и я еще не делаю их ¬¬

Кстати, почему все коды, которые я нашел, содержат это, прежде чем делать что-либо с beginBackgroundTaskWithExpirationHandler?

 bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
    [app endBackgroundTask:bgTask];
    bgTask = UIBackgroundTaskInvalid;
}];

Я думал, что это для того, чтобы взять те 600 секунд фона... но я не уверен!

2 ответа

Решение

Хорошо, проблема была в том, что я дважды вызывал beginBackgroundTaskWithExpirationHandler, один в ApplicationDidEnterBackground, а другой внутри initTimer...

Когда ваше приложение заземлено, таймер больше не будет срабатывать, если у вас не установлено значение "location" для ключа UIBackgroundModes в info.plist приложения.

Вы можете продлить время, в течение которого вам разрешено работать в фоновом режиме (если вы не установили "location"), используя beginBackgroundTaskWithExpirationHandler, но это всегда должно быть связано с соответствующим завершающим вызовом.

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