Документы для правильной загрузки данных в фоновом режиме разбросаны по нескольким документам. Некоторые ограничения не применяются 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.