NSURLConnection: путаница с порядком, в котором вызываются connection:didReceiveResponse: и connection:didFailWithError:

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

  1. Являются ли два метода делегата (т.е. connection:didReceiveResponse: и connection:didFailWithError:) взаимоисключающими друг друга? Я имею в виду, есть ли сценарий, в котором оба метода делегата могут быть вызваны объектом NSURLConnection?

  2. Если вызывается только connection:didFailWithError:, как получить код состояния HTTP?


person Rashmi Ranjan mallick    schedule 14.08.2015    source источник


Ответы (1)


Из документов:

Единственный случай, когда это сообщение не отправляется делегату, — это когда реализация протокола обнаруживает ошибку до того, как может быть создан ответ.

Справочник по классу NSURLConnectionDelegate

Таким образом, NSURLConnection может завершиться ошибкой до того, как получит ответ, но может и после. Поскольку connection:didFailWithError прекращает дальнейшие сообщения для этого соединения, могут произойти следующие два сценария:

  1. Соединение запускается, не получает ответа и вызывается соединение:didFailWithError.
  2. Соединение запускается и получает ответ, вызывается connection:didReceiveResponse:, затем по какой-то причине происходит сбой соединения (например, сетевое соединение может прерваться), прежде чем вызывается connectionDidFinishLoading.

Вам нужно будет получить код состояния HTTP из connection:didReceiveResponse, если этот метод не вызывается, код состояния отсутствует, поскольку он является частью ответа. Если вам нужно получить к нему доступ из connection:didFailWithError, вам нужно будет его записать.

Обратите внимание, что для получения кода состояния вам также потребуется преобразовать NSURLResponse в NSHTTPURLResponse следующим образом:

NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
NSLog(@"Status code %ld", httpResponse.statusCode);
person Ben Kelly    schedule 14.08.2015
comment
Итак, когда вызывается соединение: didReceiveResponse:, оно может закончиться либо соединением: didFinishLoading:, либо соединением: didFailWithError: ? - person Rashmi Ranjan mallick; 14.08.2015
comment
В случае успеха он вызовет didReceiveData:, где вам нужно записать данные (самый простой способ — использовать appendData для объекта NSMutableData) перед вызовом didFinishLoading: в случае успеха. В случае сбоя он все равно может вызвать didReceiveData перед сбоем (поскольку соединение может завершиться ошибкой в ​​любой момент). Но да, соединение должно закончиться вызовом либо connection:didFinishLoading, либо connection:didFailWithError: - person Ben Kelly; 14.08.2015
comment
Извините за поздний ответ!! Как перехватывать сетевые ошибки, такие как 400, 404, 500 и т. д. Получают ли они уведомления в соединении: didReceiveResponse: или в соединении: didFailWithError: ? - person Rashmi Ranjan mallick; 17.08.2015
comment
По сути, я хочу знать, как обрабатывать всевозможные сценарии ошибок, не упуская ничего. Могу ли я получить все ошибки в соединении: didFailWithError: или мне нужно также зависеть от соединения: didReceiveResponse:? Это будет полезно!! - person Rashmi Ranjan mallick; 17.08.2015
comment
Они получают уведомление в connection:didRecieveResponse. Эти ошибки представляют собой коды состояния сервера и являются частью ответа сервера. - person Ben Kelly; 17.08.2015
comment
Хорошо спасибо. Я вхожу в это медленно. Итак, в случае этих ошибок (400, 404, 500 и т. д.), первое соединение: didReceiveResponse: будет вызываться, как вы сказали. После этого какой метод будет вызываться. Это соединение: didFinishLoading: или соединение: didFailWithError:? - person Rashmi Ranjan mallick; 17.08.2015
comment
IIRC, вы получите didFinishLoading, если соединение не будет прервано раньше (например, из-за сбоя сети). Код ответа сервера указывает на ошибку на стороне сервера, тогда как didFailWithError обычно указывает на ошибку связи или ошибку библиотеки. Каждый из этих ответов об ошибках также содержит тело (часто просто слово «запрещено», но это может быть и целая веб-страница с пояснительным текстом). Поэтому, когда вы получаете один из этих кодов ошибок, запрос действительно выполняется успешно; он просто не предоставляет вам данные, которые вы ожидали. - person dgatwood; 15.09.2015
comment
Как правило, если вы заботитесь о теле страницы с ошибкой, продолжайте и позвольте запросу продолжать извлекать данные. В противном случае вы должны отменить запрос в методе didReceiveResponse:. Если вы это сделаете, вы больше не будете получать обратные вызовы для этого запроса. - person dgatwood; 15.09.2015