Поделиться через


Фоновая обработка в iOS с помощью задач

Самый простой способ выполнения фона в iOS — разорвать фоновые требования к задачам и запускать задачи в фоновом режиме. Задачи находятся под строгим ограничением времени и обычно получают около 600 секунд (10 минут) обработки после того, как приложение переместилось в фон в iOS 6 и менее 10 минут в iOS 7+.

Фоновые задачи можно разделить на три категории:

  1. Фоновые Сейф задачи. Вызывается в любом месте приложения, где у вас есть задача, которую вы не хотите прервать, если приложение ввело фон.
  2. Задачи DidEnterBackground. Вызывается во время DidEnterBackground метода жизненного цикла приложения, чтобы помочь в очистке и сохранении состояния.
  3. Фоновые передачи (iOS 7+) — особый тип фоновой задачи, используемой для выполнения передачи сетевых данных в iOS 7. В отличие от обычных задач, фоновые передачи не имеют предопределенного ограничения времени.

Фонобезопасные и DidEnterBackground задачи безопасны для использования в iOS 6 и iOS 7 с некоторыми незначительными различиями. Давайте рассмотрим эти два типа задач более подробно.

Создание фоновых задач Сейф

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

В следующем фрагменте кода показано, как зарегистрировать задачу для выполнения в фоновом режиме:

nint taskID = UIApplication.SharedApplication.BeginBackgroundTask( () => {});

//runs on main or background thread
FinishLongRunningTask(taskID);

UIApplication.SharedApplication.EndBackgroundTask(taskID);

Процесс регистрации связывает задачу с уникальным идентификатором, taskIDа затем заключает ее в соответствие BeginBackgroundTask и EndBackgroundTask вызовы. Чтобы создать идентификатор, мы вызываем BeginBackgroundTask метод в UIApplication объекте, а затем запустите долго выполняющуюся задачу, как правило, в новом потоке. По завершении задачи мы вызываем EndBackgroundTask и передаваем тот же идентификатор. Это важно, так как iOS завершит работу приложения, если BeginBackgroundTask вызов не соответствует.EndBackgroundTask

Внимание

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

Выполнение задач во время DidEnterBackground

Помимо того, что в фоновом режиме выполняется долго выполняющаяся задача, регистрация может использоваться для запуска задач в фоновом режиме. iOS предоставляет метод событий в классе DidEnterBackground AppDelegate, который можно использовать для сохранения состояния приложения, сохранения пользовательских данных и шифрования конфиденциального содержимого перед тем, как приложение войдет в фон. Приложение имеет примерно пять секунд, чтобы вернуться из этого метода или завершиться. Таким образом, задачи очистки, которые могут занять более пяти секунд, можно вызвать из метода DidEnterBackground . Эти задачи должны вызываться в отдельном потоке.

Процесс почти идентичен регистрации длительной задачи. Следующий фрагмент кода иллюстрирует это в действии:

public override void DidEnterBackground (UIApplication application) {
  nint taskID = UIApplication.SharedApplication.BeginBackgroundTask( () => {});
  new Task ( () => {
    DoWork();
    UIApplication.SharedApplication.EndBackgroundTask(taskID);
  }).Start();
}

Сначала мы переопределяем DidEnterBackground метод в том AppDelegateместе, где мы регистрируем задачу, BeginBackgroundTask как это было в предыдущем примере. Затем мы создадим новый поток и выполняем долговременную задачу. Обратите внимание, что EndBackgroundTask вызов теперь выполняется внутри длительной задачи, так как DidEnterBackground метод уже возвращается.

Внимание

IOS использует механизм наблюдения, чтобы гарантировать, что пользовательский интерфейс приложения остается адаптивным. Приложение, затрачивающее слишком много времени, DidEnterBackground не отвечает в пользовательском интерфейсе. Запуск задач, выполняемых в фоновом режиме, позволяет DidEnterBackground своевременно вернуться, сохраняя пользовательский интерфейс адаптивным и предотвращая убийство приложения сторожевой.

Обработка ограничений времени фоновой задачи

IOS устанавливает строгие ограничения на то, как долго может выполняться фоновая задача, и если EndBackgroundTask вызов не выполняется в течение выделенного времени, приложение будет прекращено. Отслеживая оставшееся фоновое время и используя обработчики истечения срока действия, мы можем избежать завершения приложения в iOS.

Доступ к оставшемся фоновому времени

Если приложение с зарегистрированными задачами перемещается в фон, зарегистрированные задачи получат около 600 секунд для выполнения. Мы можем проверка сколько времени задача должна завершиться с помощью статического BackgroundTimeRemaining свойства UIApplication класса. Следующий код даст нам время( в секундах), которое оставила наша фоновая задача:

double timeRemaining = UIApplication.SharedApplication.BackgroundTimeRemaining;

Предотвращение завершения работы приложения с обработчиками срока действия

Помимо предоставления доступа к BackgroundTimeRemaining свойству, iOS предоставляет грациозный способ обработки срока действия фонового времени с помощью обработчика срока действия. Это необязательный блок кода, который будет выполняться при истечении срока действия задачи. Код в обработчике срока действия вызывает EndBackgroundTask и передает идентификатор задачи, который указывает, что приложение работает хорошо и предотвращает завершение приложения iOS даже в том случае, если задача истекает. EndBackgroundTask должен вызываться в обработчике срока действия, а также в обычном ходе выполнения.

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

Task.Factory.StartNew( () => {

    //expirationHandler only called if background time allowed exceeded
    var taskId = UIApplication.SharedApplication.BeginBackgroundTask(() => {
        Console.WriteLine("Exhausted time");
        UIApplication.SharedApplication.EndBackgroundTask(taskId); 
    });
    while(myFlag == true)
    {
        Console.WriteLine(UIApplication.SharedApplication.BackgroundTimeRemaining);
        myFlag = SomeCalculationNeedsMoreTime();
    }
    //Only called if loop terminated due to myFlag and not expiration of time
    UIApplication.SharedApplication.EndBackgroundTask(taskId);
});

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

Фоновые задачи в iOS 7+

Самое большое изменение в iOS 7 относительно фоновых задач заключается не в том, как реализуются задачи, а при выполнении.

Помните, что до iOS 7 задача, выполняемая в фоновом режиме, имела 600 секунд. Одна из причин этого ограничения заключается в том, что задача, выполняемая в фоновом режиме, будет поддерживать пробуждение устройства в течение длительности задачи:

Graph of the task keeping the app awake pre-iOS 7

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

Graph of the task being broken into chunks post-iOS 7

Так как время выполнения задачи не является длительным, задачи, выполняющие передачу сети, должны обрабатываться иначе в iOS 7. Разработчикам рекомендуется использовать NSURlSession API для обработки передачи сети. В следующем разделе представлен обзор фоновой передачи данных.

Фоновые передачи

Основой фоновой передачи в iOS 7 является новый NSURLSession API. NSURLSession позволяет создавать задачи следующим образом:

  1. Передача содержимого через прерывания сети и устройства.
  2. Отправка и скачивание больших файлов ( служба фоновой передачи данных).

Давайте подробнее рассмотрим, как это работает.

NSURLSession API

NSURLSession — это мощный API для передачи содержимого по сети. Он предоставляет набор средств для обработки передачи данных через прерывания сети и изменения в состояниях приложения.

NSURLSession API создает один или несколько сеансов, которые, в свою очередь, создают задачи для шаттл блоков связанных данных в сети. Задачи выполняются асинхронно для быстрой и надежной передачи данных. Так как NSURLSession это асинхронно, для каждого сеанса требуется блок обработчика завершения, чтобы система и приложение знали, когда передача завершена.

Чтобы выполнить сетевую передачу, допустимую как для предварительной версии iOS 7, так и после iOS 7, проверка, если доступно для передачи, и используйте обычную фоновую задачу для выполнения передачи, если NSURLSession это не так:

if ([NSURLSession class]) {
  // Create a background session and enqueue transfers
}
else {
  // Start a background task and transfer directly
  // Do NOT make calls to update the UI here!
}

Внимание

Избегайте вызовов для обновления пользовательского интерфейса из фона в коде, совместимом с iOS 6, так как iOS 6 не поддерживает фоновые обновления пользовательского интерфейса и завершит работу приложения.

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

Служба фоновой передачи данных

До iOS 7 отправка или скачивание файлов в фоновом режиме была ненадежной. Фоновые задачи получают ограниченное время выполнения, но время, необходимое для передачи файла, зависит от сети и размера файла. В iOS 7 можно использовать для успешной NSURLSession отправки и скачивания больших файлов. NSURLSession Конкретный тип сеанса, который обрабатывает передачу больших файлов в фоновом режиме, называется фоновой службой передачи данных.

Передача, инициированная с помощью службы фоновой передачи, управляется операционной системой и предоставляет API для обработки проверки подлинности и ошибок. Так как передача не привязана произвольным ограничением времени, их можно использовать для отправки или скачивания больших файлов, автоматического обновления содержимого в фоновом режиме и многое другое. Дополнительные сведения о реализации службы см. в пошаговом руководстве по фоновой передаче.

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