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

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

Обратите внимание, как мы использовали там dataTask? Вы, безусловно, можете использовать это для загрузки данных. Основное различие, которое Apple описывает между dataTask и uploadTask, заключается в том, что dataTask предназначен для коротких запросов, а uploadTask позволяет вам продолжать выполнение в фоновом режиме.

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

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

*** Terminating app due to uncaught exception 'NSGenericException', reason: 'Completion handler blocks are not supported in background sessions. Use a delegate instead.'***

Черт возьми, я был избалован тем, насколько быстрые обработчики завершения. Делегаты считают 2010 год. Стоит ли мне также синтезировать свои свойства?

Хватит дерзости, давайте добавим URLSessionTaskDelegate:

И снова Xcode успешно скомпилирует этот код, но затем выйдет из строя.

*** Terminating app due to uncaught exception 'NSGenericException', reason: 'Upload tasks from NSData are not supported in background sessions.'***

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

Наконец, он не вылетит!

Остается рассмотреть еще один момент. Что, если наше приложение закроется и будет очищено из памяти до завершения загрузки? По умолчанию iOS разбудит ваше приложение и вызовет метод в вашем AppDelegate:

func application(_ application: UIApplication,
handleEventsForBackgroundURLSession identifier: String,
completionHandler: @escaping () -> Void)

Вам нужно будет воссоздать фоновый сеанс с заданным идентификатором (он будет таким же, как тот, который вы использовали для создания исходного фонового сеанса). Не забудьте также дать ему делегата! Затем ваш представитель будет уведомлен с соответствующей ответной информацией.

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

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

Последнее замечание: если по какой-то причине вы регулярно загружаете данные в свое приложение, вы можете добиться значительной экономии энергии, отложив эту загрузку до одной задачи в фоновом режиме - для получения дополнительной информации см: https://developer.apple. ru / videos / play / wwdc2018 / 228 /

Вот и все! Надеюсь, я сэкономил тебе время.

Шон имеет дело с большим объемом данных в Livefront.