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