NSURLSessionTask никогда не перезванивает, когда Wi-Fi отключен

Когда я отключаю соединение WiFi и запускаю следующий код на симуляторе iPhone 6s 10.2, обратный вызов никогда не выполняется. Я ожидал, что обратный вызов сработает довольно быстро с ошибкой типа «Нет подключения к Интернету».

NSLog(@"request-start");
NSURLRequest* request = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:@"https://www.google.com"] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:0];
task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
    NSLog(@"request-end");
}];
[task resume];

Моя проблема

Я получаю данные при первой загрузке приложения. Если Wi-Fi выключен, мне нужно показать ошибку. Если я устанавливаю тайм-аут, он соблюдается, но он должен составлять 10+ секунд, и я бы не стал заставлять их ждать. Я также пытался определить статус сети с помощью доступности, но статус сети часто равен unknown при первой загрузке приложения.


person bendytree    schedule 20.02.2017    source источник
comment
Может ли это быть из-за того, что вы используете общий сеанс?   -  person matt    schedule 20.02.2017
comment
но это должно быть 10+ секунд, и я бы не стал заставлять их ждать. Я не понимаю, если ваше соединение занимает 10 секунд, чтобы получить ответ, почему бы вам не установить тайм-аут? Вам необходимо установить тайм-аут для обработки ошибок подключения и тайм-аутов. Даже если Wi-Fi включен, это не означает, что соединение будет работать на 100%. Вы не должны сосредотачиваться на том, чтобы заставить людей ждать, а вместо этого обрабатывать ошибки и пользовательский интерфейс соответствующим образом, чтобы, возможно, отображать информационную панель прогресса для вашего пользователя, когда соединение занимает больше времени, чем ожидалось.   -  person    schedule 20.02.2017
comment
@matt - я не уверен - я пробовал defaultSessionConfiguration и ephemeralSessionConfiguration и получил те же результаты   -  person bendytree    schedule 20.02.2017
comment
@Sneak - у меня есть тайм-аут в моем реальном проекте, и я не против заставить их ждать, если есть медленное соединение. Но если нет Wi-Fi, то я бы не стал заставлять их ждать полный тайм-аут - например, ajax/browsers/curl/etc   -  person bendytree    schedule 20.02.2017


Ответы (1)


timeoutIntervalForResource

Это свойство определяет интервал времени ожидания ресурса для всех задач в сеансах на основе этой конфигурации. Интервал времени ожидания ресурса определяет, как долго (в секундах) ждать передачи всего ресурса, прежде чем отказаться от него. Таймер ресурса запускается, когда запрос инициирован, и считает до завершения запроса или достижения этого интервала времени ожидания, в зависимости от того, что наступит раньше.

Значение по умолчанию – 7 дней.

а также

timeoutIntervalForRequest

Важно

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

Значение по умолчанию – 60.

Таким образом, без установленного тайм-аута ваше соединение будет работать в течение 7 дней.

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

Источник

person Community    schedule 20.02.2017
comment
Спасибо @Sneak. Я не понимал, что это было намеренно разработано, чтобы дождаться подходящего времени, чтобы повторить запрос. Существуют ли способы сделать запрос, не дожидаясь подходящего момента для повторной попытки? - person bendytree; 20.02.2017
comment
@bendytree Ваш единственный вариант: stackoverflow .com/questions/7938650/ios-detect-3g-or-wifi/ , однако передовой опыт и рекомендации Apple заключаются в том, чтобы проверять доступность ПОСЛЕ возникновения ошибки подключения, показывать соответствующее сообщение, а не при каждом запросе, который вы делаете. Однако я не знаю, каков ваш вариант использования, это все, что вам нужно, мой друг. GL, кстати, вы должны установить тайм-аут, несмотря ни на что, чтобы не столкнуться со странными вещами. - person ; 20.02.2017
comment
Спасибо за вашу помощь. По сути, я не хочу, чтобы пользователь ждал полного тайм-аута (даже всего 10 секунд), когда явно нет соединения. Я думаю, что это просто невозможно на iOS. - person bendytree; 20.02.2017
comment
@bendytree Для одного запроса здесь и там не должно быть проблем с использованием приведенного выше решения. Однако, если вы обрабатываете много запросов и т. д., нет простого способа устранить необходимость в ошибках тайм-аута. Тем не менее, есть наблюдатель за достижимостью, который вы можете добавить для обнаружения изменений, проверьте это: kreachabilitychangednotification вызывается несколько раз">stackoverflow.com/questions/20919244/ , но помните, что ничто не гарантируется на 100%. Вы можете попробовать это. - person ; 20.02.2017