Статьи

Быстрый совет для iOS: взаимодействие с веб-сервисами

В какой-то момент в вашей карьере iOS-разработки у вас возникнет необходимость взаимодействовать с веб-сервисом из вашего приложения. Вам может понадобиться получить доступ к удаленным данным, проанализировать канал в социальной сети или даже загрузить некоторые ресурсы в ваше приложение. Этот быстрый совет научит вас делать это без использования сторонних библиотек!

Существует несколько невероятных сторонних библиотек, помогающих облегчить взаимодействие с веб-сервисами, включая ASIHTTPRequest , AFNetworking и RESTKit . Хотя эти библиотеки невероятно полезны, иногда они немного излишни. Они добавляют довольно много ненужного раздувания кода в приложение через дополнительные переменные в памяти, а также изменяют ваш рабочий процесс, чтобы приспособиться к рабочему процессу каждой библиотеки.


Я использовал некоторые из этих библиотек (и даже больше!) В качестве костыля. Я чувствовал, что их использование ускорило время разработки и уменьшило сложность. Хотя это верно во многих случаях, это не «один размер подходит всем решениям». Кроме того, вы добавляете сложность, если вы не полностью понимаете все под капотом этих библиотек.

Сегодня я собираюсь показать вам гораздо более простой подход к взаимодействию с веб-сервисами и загрузке данных из Интернета. Недавно я использовал этот подход в своем новом клиенте iOS MUD Pocket MUD Pro для извлечения удаленного аудио, настроек и данных. Этот подход предполагает использование «встроенных» технологий для загрузки, анализа и использования удаленного JSON, а также таких ресурсов, как изображения и звуки.


В версиях iOS до 4 было довольно сложно асинхронно получать данные. Обычно вам приходилось создавать полноценный класс, предназначенный для выполнения запросов, а затем другой, чтобы анализировать и использовать ответы. С помощью Central Central Dispatch (GCD) вы можете сделать это встроенным и сохранить свой код коротким и чистым. Здесь вы увидите некоторый код, который извлекает удаленный документ JSON из Интернета:

01
02
03
04
05
06
07
08
09
10
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
 
dispatch_async(queue, ^{
    NSError *error = nil;
    NSURL *url = [NSURL URLWithString:@»http://brandontreb.com/apps/pocket-mud-pro/promo.json»];
    NSString *json = [NSString stringWithContentsOfURL:url
                                              encoding:NSASCIIStringEncoding
                                                 error:&error];
    NSLog(@»\nJSON: %@ \n Error: %@», json, error);
});

Этот код начинается с выборки одной из трех очередей отправки Apple, которые вы можете использовать для асинхронного выполнения, и запускает блок в очереди с приоритетом по умолчанию. Вы могли бы так же легко создать свою собственную очередь. В любом случае, это позволяет нашему коду запускаться в отдельном потоке от основного потока через мощь Grand Central Dispatch (GCD).

Затем мы создаем URL-адрес и вставляем его в stringWithContentsOfURL:encoding:error: метод NSString для извлечения данных JSON. Наконец, возвращаемая строка выводится вместе с ошибкой (если она есть).

Этот подход очень быстрый, но не дает вам тонны контроля. Хотя вы знаете, что это может быть за ошибка, она не позволяет вам указать тайм-аут в случае ошибки. Время ожидания по умолчанию составляет около 30 секунд. Если вам нужен какой-то дополнительный контроль времени ожидания и тому подобное, замените строковый метод на NSURLConnection.


Начиная с iOS 5, Apple имеет встроенный анализатор JSON, который позволяет вам взять строку, содержащую JSON, и преобразовать ее в NSDictionary или NSArray. Чтобы проанализировать и использовать JSON, возвращенный в приведенном выше коде, добавьте эти строки до конца блока:

1
2
3
4
5
6
7
if(!error) {
    NSData *jsonData = [json dataUsingEncoding:NSASCIIStringEncoding];
    NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:jsonData
                                                                options:kNilOptions
                                                                  error:&error];
    NSLog(@»JSON: %@», jsonDict);
}

Класс NSJSONSerialization проанализирует и преобразует строку JSON в NSDictionary или NSArray в зависимости от формата вашего JSON. Это делает вашу жизнь намного проще. Теперь вы можете использовать значения из строки JSON следующим образом:

1
NSString *promo_url = [jsonDict objectForKey:@»promo_url»];

И вот оно! Очень простой способ использовать веб-сервисы, используя ТОЛЬКО собственные классы SDK. Теперь перейдем к чему-то более интересному … изображениям!


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

01
02
03
04
05
06
07
08
09
10
11
12
13
dispatch_queue_t img_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(img_queue, ^{
     
    NSURL *url = [NSURL URLWithString:@»http://imgs.xkcd.com/comics/formal_logic.png»];
    NSError *error = nil;
    NSData *image = [NSData dataWithContentsOfURL:url options:0 error:&error];
     
    if(!error && image && [image length] > 0) {
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
        NSString *path = [[paths objectAtIndex:0] stringByAppendingPathComponent:@»image.png»];
         
        [image writeToFile:path options:0 error:&error];
    }

Опять же, мы начинаем с получения очереди для асинхронного запуска. Затем мы выбираем данные изображения, используя dataWithContentsOfURL:options:error: метод NSData. Убедившись, что мы вернули некоторые данные, мы берем ссылку на каталог caches на диске и сохраняем образ.

И это так просто! Вы также можете сразу использовать полученное изображение, выполнив это:

1
UIImage *img = [UIImage imageWithData:image];

Я надеюсь, что эта статья помогла вам избавиться от сторонних библиотек для взаимодействия с сетью. Теперь у вас должны быть знания для создания полноценного веб-приложения. Если у вас есть какие-либо вопросы или комментарии, пожалуйста, оставьте их здесь или напишите мне в Twitter .

Удачного кодирования!