воскресенье, 16 марта 2014 г.

Руководство. Как использовать iOS NSURLConnection на примере

Перевод http://codewithchris.com/tutorial-how-to-use-ios-nsurlconnection-by-example/

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

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

1. Пример асинхронного запроса


Чтобы загрузить данные, мы должны сделать три шага:

1. Наш класс должен соответствовать протоколу NSURLConnectionDelegate и содержать переменную для хранения ответа сервера
2. Реализовать методы протокола NSURLConnectionDelegate
3. Создать экземпляр NSURLRequest и NSURLConnection для отправки запроса

Идея в том, что в шаге 3 вы отправляете запрос и собираетесь получать уведомления о некоторых событиях, которые могут произойти при получении ответа. Обработка событий происходит в методах, объявленных и реализованных в шаге 2. На шаге 1 вы сообщаете, что хотите обрабатывать события NSURLConnection.

Шаг 1. 


В классе где вы собираетесь использовать NSURLConnection укажите в заголовочном файле что будет использоваться протокол NSURLConnectionDelegate. Также объявите переменную для хранения ответа сервера.
 @interface ViewController : UIViewController<NSURLConnectionDelegate>  
 {  
   NSMutableData *_responseData;  
 }  

Шаг 2

Далее пишем методы протокола NSURLConnection. В комментариях к коду, вы можете увидеть, для чего используется каждый метод протокола:

 #pragma mark NSURLConnection Delegate Methods  
 - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {  
   // Ответ был получен, здесь мы инициализируем переменную которую вы создали
   // и в которую мы позже добавим данные в методе didReceiveData
   // Кроме того этот метод вызывается каждый раз при редиректе для переинициализации   
   // переменных  
   _responseData = [[NSMutableData alloc] init];  
 }  
 - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {  
   // Добавить новые данные в переменную которую вы объявили  
   [_responseData appendData:data];  
 }  
 - (NSCachedURLResponse *)connection:(NSURLConnection *)connection  
          willCacheResponse:(NSCachedURLResponse*)cachedResponse {  
   // Возвращает nil чтобы показать что нет необходимости кэшировать ответ  
   return nil;  
 }  
 - (void)connectionDidFinishLoading:(NSURLConnection *)connection {  
   // Запрос выполнени и данные были получены
   // Здесь можно обработать вашу объявленную переменную
 }  
 - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {  
   // По каким-то причинам запрос не выполнен  
   // Нужно проверить переменную error с кодом ошибки
 }  

Шаг 3

Теперь вы готовы выполнить асинхронный запрос. Создайте экземпляр NSURLRequest, установите ему URL. Затем создайте экземпляр NSURLConnection и вызовите метод initWithRequest, используя в качестве параметра NSURLRequest:


 // Создать запрос.  
 NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://google.com"]];  
 // Создать соединение и послать запрос  
 NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];  

Шаг 4

Что должно произойти когда ваш запрос отправлен в шаге 3? Первым будет вызван connection:didReceiveResponse показывая, что пришел ответ от сервера. Далее несколько раз вызывается connection:didReceiveData, здесь добавляются последние данные в переменную. И наконец, срабатывает connectionDidFinishLoading, где можно обработать переменную.

Если вы хотите сделать запрос синхронным, вы можете использовать метод
sendSynchronousRequest NSURLConnection

2. Пример синхронного запроса

Синхронный запрос выглядит следующим образом:
 // Отправка синхронного запроса  
 NSURLRequest * urlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://google.com"]];  
 NSURLResponse * response = nil;  
 NSError * error = nil;  
 NSData * data = [NSURLConnection sendSynchronousRequest:urlRequest  
                      returningResponse:&response  
                            error:&error];  
 if (error == nil)  
 {  
   // Обрабатываем здесь данные  
 }  

По прежнему необходима NSURLRequest. Переменные NSURLResponse и NSError   передаются в метод sendSynchronousReqeust и когда он возвращает данные, они будут содержать поток данных и ошибки (если таковые имеются). Если вам нужно проверить на такие вещи как код ответа, вы можете сделать это при помощи переменной "response" из строки 6.

Запрос из строки 5 выполняется синхронно, результаты присваиваются переменной NSData. Перед тем как обрабатывать ответ, необходимо проверить error на отсутствие ошибок (эквивалентность nil).

Синхронный или асинхронный?


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

3. Отправка данных POST


Для отправки данных методом POST, всё что вам нужно сделать, это использовать NSURLRequest как мы делали раньше, но на этот раз нужно установить свойство HTTPMethod в значение POST и установить отправляемые поля. Затем NSURLConnection устанавливается как обычно с разницей лишь в том, что используется экземпляр
NSMutableURLRequest, т.к. его свойства устанавливаются после инициализации.


 // Создаем запрос  
 NSMutableURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://google.com"]];  
 // Устанавливаем метод в POST  
 request.HTTPMethod = @"POST";  
 // Устанавливаем поля заголовка  
 [request setValue:@"application/xml; charset=utf-8" forHTTPHeaderField:@"Content-Type"];  
 // Преобразоване ваших данный и установка свойства HTTPBody  вашего запроса   
 NSString *stringData = @"some data";  
 NSData *requestBodyData = [stringData dataUsingEncoding:NSUTF8StringEncoding];  
 request.HTTPBody = requestBodyData;  
 // Создание url соединения и отправка запроса  
 NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];  


4. Пример установки таймаута соединения

 Если вы хотите установить таймаут ответа от сервера, вы должны установить свойство timeoutInterval  объекта NSURLRequest. Если вы получили сообщение об ошибке в XCode, убедитесь что используете экземпляр NSMutableURLRequest, т.к. NSURLRequest не может быть изменен


5. Политика кэширования

Если вы не определили политику кэширования в вашем NSURLRequest, он будет пытаться определить их по своему состоянию. Например, с HTTP он будет смотреть на заголовки ответов и пытаться следовать их указаниям о кэшировании. Другие примеры и информация о кэшировании в NSURLConnection  можно найти в посте caching problems with NSURLConnection.


Видеоурок 1 [ENG]:

Комментариев нет: