timeoutIntervalForRequest NSURLSessionConfiguration не работает с фоновым URLSession

Я следовал этому уроку Загрузка файлов в фоновом режиме с помощью URLSessionDownloadTask

И это Apple Doc Загрузка файлов в фоновом режиме

Я попытался настроить, потому что у нас есть долго работающий API

let config = URLSessionConfiguration.background(withIdentifier: "\(Bundle.main.bundleIdentifier!).background")
    config.timeoutIntervalForRequest = 120
    config.timeoutIntervalForResource = 180

Но я столкнулся с этой странной проблемой:

Если сервер не отвечает ни с каким фрагментом данных, это означает, что

func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64)

не вызывается вообще.

Приложение прервет предыдущий запрос и повторяет новый запрос каждые 66 секунд. Я не знаю, откуда взялась эта цифра, но из моего эксперимента примерно 66 секунд.

Если я установлю timeoutIntervalForRequest = 10 Конечно, приложение будет повторять запрос каждые 10 секунд, но любая попытка установить его выше 66 секунд не работает

Не уверен, что кто-то сталкивался с той же проблемой и нашел решение.

Только 1 примечание: время ожидания истекает через 180 секунд, и приложение перестает повторять новые запросы

1 ответ

Во-первых, это ошибка. Пожалуйста, отправьте его на bugreport.apple.com. Тайм-аут не следует игнорировать, как это. Конечно, есть хороший шанс, что это проблема управления питанием, которая не будет устранена, поэтому я не буду задерживать дыхание.

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

По сути, на мобильном устройстве вы действительно не должны по какой-либо причине держать открытым соединение с удаленным сервером. Это приводит к значительному расходу батареи, чтобы постоянно поддерживать радио Wi-Fi, а тем более сотовую радиосвязь, и, что еще хуже, такое соединение может прерваться в любое время, когда пользователь выходит из зоны действия, переключает сотовые станции или иным образом теряет связь. Сети дерьмовые - сотовые сети вдвойне.

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

  • Сделайте запрос к серверу.
  • Попросите сервер отправить вам уникальный идентификатор, связанный с запросом, и, по желанию, предполагаемое время завершения.
  • Дождитесь приблизительного времени завершения, затем спросите сервер, как идут дела (предоставив этот уникальный идентификатор).
  • Продолжайте периодически опрашивать сервер, пока сервер не сообщит, что задача выполнена (или не выполнена).
  • Когда сервер сообщает, что задача выполнена, выполните запрос на получение результатов, а затем запрос на освобождение завершенных результатов.
  • Периодически очищайте старые, не собранные результаты на сервере с помощью задания cron или аналогичного.

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

Другие вопросы по тегам