2016-01-19 1 views
0

Я работаю над sdk, который использует NSTimer для вызова сервера, когда он истекает через x минут, и серверный вызов сбрасывает таймер обратно на x минут после выполнения некоторой работы. Проблема, с которой я сталкиваюсь, заключается в том, что мой таймер перестает работать, когда мое приложение находится в фоновом режиме и немедленно возобновляется, когда мое приложение снова появляется на переднем плане. Как мне заставить это работать?Фоновый режим с NSTimers и вызовами сервера

//initialize self.myTimer somewhere in my code 
//called once somewhere in my code-->[self resetTimer:self.myTimer expiry:30]; 

- (void)resetTimer:(NSTimer *)timer expiry:(float)seconds { 
[timer invalidate]; 
NSTimer *newTimer = [NSTimer timerWithTimeInterval:seconds 
              target:self 
              selector:@selector(updateTimer:) 
              userInfo:nil 
              repeats:NO]; 
[[NSRunLoop mainRunLoop] addTimer:newTimer forMode:NSRunLoopCommonModes]; 

self.myTimer = newTimer; 

} 

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

    [timer invalidate]; 

    dispatch_queue_t queue = dispatch_queue_create("update", NULL); 
    dispatch_async(queue, ^{ 
    [self serverCall]; 
    }); 
} 

-(void)serverCall{ 
//make server call and do some work 
[self resetTimer:self.myTimer expiry:30]; 


} 

ответ

3

Таймер не будет продолжать срабатывать, когда приложение находится в фоновом режиме. Если вы хотите, чтобы ОС задавала темп вызовов сервера, вы можете выполнить это, обратившись к разделу «Получение небольших объемов контента оппортунистически» в этом background execution doc.

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

Когда IOS решает предоставить ваше приложение несколько циклов, вы можете запустить короткую задачу:

- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler { 
    [self serverCall]; // BUT! read on 
} 

Но вам нужно реорганизовать serverCall сказать абоненту, когда его сделали. В противном случае вы не будете знать, когда нужно вызывать completionHandler:.

- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler { 
    [self newServerCallWithCompletion:^(BOOL gotNewData) { 
     UIBackgroundFetchResult result = (gotNewData)? UIBackgroundFetchResultNewData : UIBackgroundFetchResultNoData; 
     completionHandler(result); 
    }]; 
} 

См. Документы для получения дополнительных опций на UIBackgroundFetchResult.

С этим iOS задаст темп запросов, так что вы не сможете сделать их чаще, чем когда вам приложено задание. Сохраняя время последнего запроса, вы можете делать запросы реже. Просто проверьте, является ли интервал с последнего запроса <= до некоторой желаемой максимальной частоты. Если это так, просто позвоните в completeHandler сразу с «no data».

+0

Метод performFetchWithCompletionHandler, по-видимому, доступен только в делегате приложения. В настоящее время я работаю над статической библиотекой, у которой нет appdelegate. Я мог бы добавить это в мое тестовое приложение, которое использует мою статическую библиотеку, но это побеждает цель создания статической библиотеки. Я все еще хочу использовать свои таймеры, когда я нахожусь на переднем плане для выполнения вызовов сервера и переключается на другой метод, который позволяет мне выполнять вызовы сервера, когда мое приложение находится в фоновом режиме. Это возможно? – iamarnold

+0

Несомненно, на переднем плане подход к таймеру хорош. Но единственный способ выполнить обработку в фоновом режиме - это перехватывать делегат приложения. Для этого в библиотеке вам нужно будет предоставить инструкции по установке клиента вашей библиотеки для настройки info.plist и добавить вызов в вашу библиотеку в делегате приложения. (вы хотите, чтобы клиент библиотеки знал и одобрял обработку фона в любом случае). – danh

+0

Что произойдет, если у меня есть разные серверные вызовы, которые я хочу вызывать в разное время? Допустим, у меня есть таймер A через 5 минут, который вызывает метод A и таймер B через 10 минут, который вызывает метод B. Таймеры отлично работают на переднем плане, но как настроить эквивалент в фоновом режиме с помощью функции performFetchWithCompletionHandler? – iamarnold

 Смежные вопросы

  • Нет связанных вопросов^_^