5

У меня возникла проблема, когда речь идет о медленном бэкэнд и загрузке данных с помощью конфигурации фона.NSURLSessionDownloadTask продолжает повторять попытку при использовании конфигурации фона

NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration backgroundSessionConfiguration:identifier]; 
_backgroundSession = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:nil]; 
NSURLSessionDownloadTask *downloadTask = [_backgroundSession downloadTaskWithURL:URL]; 
[downloadTask resume]; 

Если соединение astablished, но она занимает более 60 секунд для того, чтобы отправить обратно данных происходит тайм-аут. Это нормально. Однако поведение, которое я испытываю, заключается в том, что я не получаю сообщение об ошибке. Сессия просто отправляет новый запрос. «Дайте мне данные снова». Я понятия не имею, где это происходит. Не в моем коде и не вызываются методы делегата, о которых я знаю. Я просто имею доступ к журналам сервера. Серверу требуется примерно 68 секунд для отправки данных, но приложение просто игнорирует его, потому что ожидает нового запроса.

Одним из решений является увеличение значения таймаута. Но мне не нравится это, и это работает только для прошивки 7. Не IOS 8.

sessionConfig.timeoutIntervalForRequest = 10 * 60.0; 

Кто-нибудь есть какие-либо понять в этом? Я нашел это link about timeout issue for background session здесь, в stackoverflow. Это 10 месяцев, но нет решений, только люди соглашаются.

ответ

3

Мне это удалось. Я не говорю, что мое решение решение, но это a решение.

Поведение, с которым я столкнулся, заключается в том, что iOS 7 и iOS 8 придают приоритет свойствам по-разному. У меня есть два места для установки этих свойств таймаута, NSURLSessionConfiguration и в NSMutableURLRequest. iOS 7 не заботится о свойствах запросов, а iOS 8 не может заботиться о свойствах конфигурации. Сейчас мое решение выглядит следующим образом:

NSURLSessionConfiguration *sessionConfig; 
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) { 
    sessionConfig = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:identifier]; 
} 
else { 
    sessionConfig = [NSURLSessionConfiguration backgroundSessionConfiguration:identifier]; 
} 
if ([[[UIDevice currentDevice] systemVersion] floatValue] < 8.0) { 
    sessionConfig.timeoutIntervalForRequest = 5 * 60.0; 
} 
_backgroundSession = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:nil]; 

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL]; 
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) { 
    request.timeoutInterval = 5 * 60.0; 
} 
NSURLSessionDownloadTask *downloadTask = [_backgroundSession downloadTaskWithRequest:request]; 

Я думаю, можно было бы просто не сделать проверку SystemVersion и установить оба свойства с тем же значением. Хотя я твердо верю, что меньше кода больше, я считаю, что еще сильнее, не затрагивая состояния, которые не должны быть затронуты. Однако я хотел бы услышать народы . И если у кого-то есть лучшее решение, пожалуйста, share.

О, еще одна вещь. Повторяющаяся часть будет продолжаться до тех пор, пока timeoutIntervalForResource не достигнет значения по умолчанию 7 дней в соответствии с документацией. Я уменьшил это до 10 минут.

sessionConfig.timeoutIntervalForResource = 10 * 60; 

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

Update

Мы изменили timeoutIntervalForResource назад к значению по умолчанию 7 дней. Например, у нас есть клиенты в Китае, и некоторые из них действительно плохо связаны. Главный лимит в 10 минут был просто глупым.

Обязательно проверьте Sunkas answer для лучшего качества кода. Однако мой фрагмент кода распространяется на разные классы, поэтому я не могу повторно использовать этот подход на 100%.

+0

Вопрос: почему вы делаете различие между прошивкой 8 и прошивкой 7 после того, как все? Не могли бы вы установить как timeoutIntervalForRequest, так и timeoutInterval? – dlinsin

6

не мог остановить себя, вот ваш ответ немного переработан :)

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL]; 
NSURLSessionConfiguration *sessionConfig; 
float timeout = 5 * 60.0f; 

BOOL iOS8OrNewer = [[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0; 
if (iOS8OrNewer) { 
    sessionConfig = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:identifier]; 
    request.timeoutInterval = timeout; 
} 
else { 
    sessionConfig = [NSURLSessionConfiguration backgroundSessionConfiguration:identifier]; 
    sessionConfig.timeoutIntervalForRequest = timeout; 
} 

_backgroundSession = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:nil]; 

NSURLSessionDownloadTask *downloadTask = [_backgroundSession downloadTaskWithRequest:request]; 
+2

Очень приятно и легко читать, спасибо! Хотя мой фрагмент кода фактически распространяется по двум отдельным классам, но я буду применять то, что я могу от него :) –

3

С iOS8 года NSUrlSession в фоновом режиме не вызывает этот метод делегата, если сервер не отвечает. -(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error Загрузка/выгрузка остается бездействующей на неопределенный срок. Этот делегат вызывается на iOS7 с ошибкой, когда сервер не отвечает.

Как правило, фоновый сеанс NSURLSession не выполняет задачу, если что-то пойдет не так на провод. Скорее, он продолжает искать подходящее время для запуска запроса и повторных попыток в это время. Это продолжается до истечения времени ожидания ресурса (то есть значения свойства timeoutIntervalForResource в объекте NSURLSessionConfiguration, который вы используете для создания сеанса). Текущее значение по умолчанию для этого значения - одна неделя! Другими словами, поведение ошибки в тайм-ауте в iOS7 было неверным. В контексте фонового сеанса более интересным является немедленное прерывание из-за сетевых проблем. Так как iOS8, задача NSURLSession продолжается, даже если она сталкивается с таймаутами и потерей сети. Он продолжается, но до тех пор, пока не будет достигнут тайм-аутIntervalForResource.

Так что в основном timeoutIntervalForRequest не будет работать в фоновом режиме, но timeoutIntervalForResource будет.

Источник: Apple Forum

Смежные вопросы