iOS. Приемы программирования Нахавандипур Вандад
NSURLResponse *response = nil;
NSError *error = nil;
NSData *data = [NSURLConnection sendSynchronousRequest: urlRequest
returningResponse:&response
error:&error];
if ([data length] > 0 &&
error == nil){
NSLog(@"%lu bytes of data was returned.", (unsigned long)[data length]);
}
else if ([data length] == 0 &&
error == nil){
NSLog(@"No data was returned.");
}
else if (error!= nil){
NSLog(@"Error happened = %@", error);
}
});
NSLog(@"We are done.");
self.window = [[UIWindow alloc] initWithFrame:
[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
Вывод будет примерно таким:
We are here…
Firing synchronous url connection…
We are done.
2 52450 bytes of data was returned.
Итак, в данном примере текущий поток вывел текст We are done в окне консоли, не дожидаясь, пока синхронное соединение завершит считывание с заданного URL. Интересно, правда? Таким образом, этот пример доказывает, что при умелом обращении синхронное URL-соединение не обязательно блокирует главный поток. Тем не менее оно гарантированно блокирует текущий поток.
11.4. Изменение URL-запроса с применением NSMutableURLRequest
Постановка задачи
Требуется корректировать различные HTTP-заголовки и настройки URL-запроса перед передачей его URL-соединению.
Решение
Эта техника лежит в основе некоторых разделов, рассмотренных далее в этой главе. Пользуйтесь NSMutableURLRequest вместо NSURLRequest.
Обсуждение
URL-запрос может быть изменяемым или неизменяемым. URL-запросы, относящиеся к первой категории, поддаются изменениям после выделения и инициализации, а те, что относятся ко второй категории, — нет. Этот раздел посвящен изменяемым URL-запросам. Их можно создавать с помощью класса NSMutableURLRequest.
Рассмотрим пример, в котором длительность задержки при URL-запросе изменяется после выделения и инициализации этого запроса:
NSString *urlAsString = @"http://www.apple.com";
NSURL *url = [NSURL URLWithString: urlAsString];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL: url];
[urlRequest setTimeoutInterval:30.0f];
Теперь обратимся к другому примеру, где URL и время задержки при URL-запросе задаются после выделения и инициализации:
NSString *urlAsString = @"http://www.apple.com";
NSURL *url = [NSURL URLWithString: urlAsString];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest new];
[urlRequest setTimeoutInterval:30.0f];
[urlRequest setURL: url];
В других разделах этой главы мы изучим некоторые очень тонкие приемы, которые осуществимы с помощью изменяемых URL-запросов.
11.5. Отправка запросов HTTP GET с применением NSURLConnection
Постановка задачи
Необходимо отправить запрос GET по протоколу HTTP и, возможно, передать получателю вместе с этим запросом какие-либо параметры.
Решение
По определению GET-запросы допускают указание параметров в строках запросов в общеизвестной форме:
http://example.com/?param1=value1¶m2=value2…
Строки можно использовать для перечисления параметров в обычном формате.
Обсуждение
GET-запрос — это запрос к веб-серверу на получение данных. Обычно запрос сопровождается параметрами, которые отправляются в строке запроса как часть URL.
Чтобы протестировать вызов GET, необходимо найти веб-сервер, принимающий такие вызовы и способный отослать какие-либо данные в ответ. Это просто. Как вы уже знаете, при открытии веб-страницы в браузере этот браузер по умолчанию посылает запрос GET к конечной точке. Поэтому данный раздел вы можете опробовать на любом сайте по своему усмотрению.
Для симулирования отправки параметров строки запроса в GET-запросе к той же веб-службе с помощью NSURLConnection воспользуемся изменяемым URL-запросом и явно укажем ваш HTTP-метод для GET с помощью метода setHTTPMethod:, относящегося к NSMutableURLRequest. Параметры оформляются как часть URL, следующим образом:
— (BOOL) application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
NSString *urlAsString = <# Здесь укажите URL веб-сервера #>;
urlAsString = [urlAsString stringByAppendingString:@"?param1=First"];
urlAsString = [urlAsString stringByAppendingString:@"¶m2=Second"];
NSURL *url = [NSURL URLWithString: urlAsString];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest
requestWithURL: url];
[urlRequest setTimeoutInterval:30.0f];
[urlRequest setHTTPMethod:@"GET"];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection
sendAsynchronousRequest: urlRequest
queue: queue
completionHandler: ^(NSURLResponse *response,
NSData *data,
NSError *error) {
if ([data length] >0 &&
error == nil){
NSString *html = [[NSString alloc] initWithData: data
encoding: NSUTF8StringEncoding];
NSLog(@"HTML = %@", html);
}
else if ([data length] == 0 &&
error == nil){
NSLog(@"Nothing was downloaded.");
}
else if (error!= nil){
NSLog(@"Error happened = %@", error);
}
}];
self.window = [[UIWindow alloc] initWithFrame:
[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
Переменная urlAsString в данном коде представляет собой сущность Xcode, которая называется «шаблон переменной». Если скопировать этот код и вставить его в ваш проект Xcode, переменная будет отображена так, как показано на рис. 11.1. Перед запуском этого примера кода убедитесь, что присвоили вышеупомянутой переменной валидный URL.
Рис. 11.1. Заменяемая переменная в Xcode
Единственный момент, который необходимо учитывать, заключается в том, что перед первым параметром ставится вопросительный знак, а перед всеми последующими — амперсанд (&). Вот и все! Теперь вы можете пользоваться методом HTTP GET и отправлять параметры в строке запроса.
11.6. Отправка запросов HTTP POST с применением NSURLConnection
Постановка задачи
Необходимо вызвать метод HTTP POST веб-сервера и, возможно, передать параметры (в теле HTTP или в строке запроса) определенной веб-службе.
Решение
Как и в случае с методом GET, можно использовать метод POST с применением NSURLConnection. Следует явно задать метод нашего URL как POST.
Обсуждение
Напишем простое приложение, которое может создать асинхронное соединение и отослать ряд параметров в виде строки запроса и нескольких параметров в теле HTTP-запроса по URL:
— (BOOL) application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
NSString *urlAsString = <# Здесь укажите URL веб-сервера #>;
urlAsString = [urlAsString stringByAppendingString:@"?param1=First"];
urlAsString = [urlAsString stringByAppendingString:@"¶m2=Second"];
NSURL *url = [NSURL URLWithString: urlAsString];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL: url];
[urlRequest setTimeoutInterval:30.0f];
[urlRequest setHTTPMethod:@"POST"];
NSString *body = @"bodyParam1=BodyValue1&bodyParam2=BodyValue2";
[urlRequest setHTTPBody: [body dataUsingEncoding: NSUTF8StringEncoding]];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection
sendAsynchronousRequest: urlRequest
queue: queue
completionHandler: ^(NSURLResponse *response,
NSData *data,
NSError *error) {
if ([data length] >0 &&
error == nil){
NSString *html = [[NSString alloc] initWithData: data
encoding: NSUTF8StringEncoding];
NSLog(@"HTML = %@", html);
}
else if ([data length] == 0 &&
error == nil){
NSLog(@"Nothing was downloaded.");
}
else if (error!= nil){
NSLog(@"Error happened = %@", error);
}
}];
self.window = [[UIWindow alloc] initWithFrame:
[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
Первый параметр, пересылаемый в теле HTTP, не обязательно предварять вопросительным знаком, а пересылаемый в строке запроса — обязательно.
11.7. Отправка запросов HTTP DELETE с применением NSURLConnection
Постановка задачи
Требуется вызвать веб-службу методом HTTP DELETE, чтобы удалить ресурс, расположенный по ссылке URL, и, возможно, передать веб-службе определенные параметры, которые будут находиться в теле HTTP или в строке запроса.
Решение
Как и методы GET и POST, метод DELETE можно использовать с помощью NSURLConnection. Необходимо явно задать метод вашего URL как DELETE.
Обсуждение
Напишем простое приложение, которое будет создавать асинхронное соединение и отправлять несколько параметров в строке запроса, а несколько — в теле HTTP. Отправка будет происходить по указанному URL с помощью метода DELETE HTTP:
— (BOOL) application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
NSString *urlAsString = <# Здесь укажите URL веб-сервера #>;
urlAsString = [urlAsString stringByAppendingString:@"?param1=First"];
urlAsString = [urlAsString stringByAppendingString:@"¶m2=Second"];
NSURL *url = [NSURL URLWithString: urlAsString];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL: url];
[urlRequest setTimeoutInterval:30.0f];
[urlRequest setHTTPMethod:@"DELETE"];
NSString *body = @"bodyParam1=BodyValue1&bodyParam2=BodyValue2";
[urlRequest setHTTPBody: [body dataUsingEncoding: NSUTF8StringEncoding]];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection
sendAsynchronousRequest: urlRequest
queue: queue
completionHandler: ^(NSURLResponse *response,
NSData *data,
NSError *error) {
if ([data length] >0 &&
error == nil){
NSString *html = [[NSString alloc] initWithData: data
encoding: NSUTF8StringEncoding];
NSLog(@"HTML = %@", html);
}
else if ([data length] == 0 &&
error == nil){
NSLog(@"Nothing was downloaded.");
}
else if (error!= nil){
NSLog(@"Error happened = %@", error);
}
}];
self.window = [[UIWindow alloc] initWithFrame:
[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
Этот пример очень напоминает код, рассмотренный в разделах 11.5 и 11.6. Разница заключается в том, что здесь мы использовали HTTP-метод DELETE. Прочая информация практически идентична той, что была изложена в упомянутых разделах.
11.8. Отправка запросов HTTP PUT с применением NSURLConnection
Постановка задачи
Требуется вызывать веб-службу методом HTTP PUT, чтобы размещать ресурс на веб-сервере и, возможно, передать веб-службе определенные параметры, которые будут находиться в теле HTTP или в строке запроса.
Решение
Как и методы GET, POST и DELETE, метод PUT можно использовать с помощью NSURLConnection. Необходимо явно задать метод вашего URL как PUT.
Обсуждение
Напишем простое приложение, которое будет создавать асинхронное соединение и отправлять несколько параметров в строке запроса, а несколько — в теле HTTP. Отправка будет происходить по указанному URL с помощью метода PUT:
— (BOOL) application:(UIApplication *)application