6

У меня есть некоторый длительный процесс, который я хочу запустить, даже если приложение идет в фоновом режиме. Я вызываю метод beginBackgroundTaskWithExpirationHandler: приложения и в expirationBlock я вызываю приложение endBackgroundTask. Вот реализация:beginBackgroundTaskWithExpirationHandler вызывает endBackgroundTask, но не завершает процесс

__block UIBackgroundTaskIdentifier task = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ 
    [[UIApplication sharedApplication] endBackgroundTask:task]; 
    task = UIBackgroundTaskInvalid; 
}]; 
dispatch_queue_t queue = dispatch_queue_create("com.test.test1234", DISPATCH_QUEUE_SERIAL); 
dispatch_async(queue, ^{ 
    // My Task goes here 
}); 

В некоторых случаях мой серийный очереди больше задач на выполнение которых не может быть завершена в срок, предусмотренный системой. Таким образом, блок завершения истечет, и в этом я заканчиваю UIBackgroundTaskIdentifier, но не останавливаю процесс отправки (я даже не могу отменить отправку).

документ от Apple говорит:

Каждый вызов beginBackgroundTaskWithName: expirationHandler: или beginBackgroundTaskWithExpirationHandler: метод генерирует уникальный ключ, который будет связан с соответствующей задачей. Когда ваше приложение завершает задачу, оно должно вызвать метод endBackgroundTask: с соответствующим токеном, чтобы система узнала, что задача завершена. Невозможность вызвать метод endBackgroundTask: для фоновой задачи приведет к прекращению действия вашего приложения. Если вы предоставили обработчик срока действия при запуске задачи, система вызывает этот обработчик и дает вам последний шанс прекратить выполнение задачи и избежать ее завершения.

Итак, в соответствии с этим, если я не звоню endBackgroundTask:, мое приложение будет прекращено, что нормально.

Мой вопрос: с моей текущей реализацией что делать, если я вызываю endBackgroundTask: в expirationHandler и моя задача очереди отправки не заполняется? Мое приложение будет прекращено или будет приостановлено?

благодаря

+0

если вы вызвали endBackgroundTask: в любом месте вашей очереди. он просто приостановил ваше приложение, поставив приложение во сне. –

+0

@chiragshah, так что это не может быть причиной сторожевого пса, чтобы убить мое приложение? watchdog убьет приложение, только если я пропущу «endBackgroundTask»? –

+0

да, я тоже думаю, что в моем приложении он может нормально работать –

ответ

11

Вот некоторые сценарии, которые вам нужно работать, используя beginBackgroundTaskWithExpirationHandler в противном случае ваше приложение будет terminate.

Сценарий 1: Приложение настроено на Foreground. вы начинаете beginBackgroundTaskWithExpirationHandler, затем введите Background режим. ваше приложение держится надолго.

Сценарий 2: ваше приложение работает от Foreground. вы начинаете beginBackgroundTaskWithExpirationHandler, затем введите Background режим. Затем вернитесь в режим Foreground, и вы не вызываете endBackgroundTask, а затем ваше приложение все еще execute background queue, поэтому он будет расширять этот процесс для следующего 3 minute (после того, как IOS 7 представит перед IOS 7, время выполнения процесса составляло 10 минут). так что вам нужно будет отменить фоновые очереди, а задача выйдет из фоновой очереди и введите в очередь переднего плана.

Так вот код, который показывает вам. что лучше всего обрабатывать фоновый процесс.

Шаг 1: Объявление __block UIBackgroundTaskIdentifier bgTask как глобальная переменная.

Шаг 2: Чтобы добавить следующий код в applicationDidEnterBackground.

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

     bgTask = [application beginBackgroundTaskWithExpirationHandler:^{ 
     bgTask = UIBackgroundTaskInvalid; 
      }]; 

} 

Шаг 3: Остановить обработчик фоновой задачи один раз и приложения приходят в режиме переднего плана.

- (void)applicationWillEnterForeground:(UIApplication *)application { 
    // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 

    [[UIApplication sharedApplication] endBackgroundTask:bgTask]; 

} 
+0

спасибо за ответ. В сценарии 2, что, если я не буду называть endBackgroundTask, когда приложение выходит на передний план? Я уже вызываю endBackgroundTask в блоке expiration. –

+0

Компилятор поймет, что ваша фоновая очередь все равно выполняется, поэтому ее выполнение выполняется до следующих 3 минут после того, как этот компилятор завершит ваше приложение. это сценарий, который случается со мной. –

1

Если вы не вызываете endBackgroundTask в обработчике истечения срока, ваше приложение будет прекращено.

Как только вы вызываете endBackgroundTask у своего обработчика истечения срока действия, вы сообщаете ОС «Хорошо, я закончил с сохранением важных задач. Это зависит от вас». После этого ваше приложение может быть приостановлено на некоторое время и прекращено позже, или оно может быть немедленно прекращено в зависимости от системных ресурсов.

+0

или он может оставаться в фоновом режиме из-за других задач ... – Honey