Arm1.ru

Работа с JSON (парсинг) в Objective-C при разработке под iOS

Ещё один пост, чтобы у самого в голове улеглось. Про работу с JSON в Objective-C на примере парсинга твитов из публичной ленты Twitter.

В Objective-C из коробки нет ничего для того, чтобы работать с данными в формате JSON. Есть только для работы с XML. Но есть фреймворк для работы с JSON, в случае если вас к этому вынуждает необходимость/прихоть/нежелание начальника отдавать данные в XML (нужное подчеркнуть). Его можно скачать на GitHub. На данный момент последняя версия 3.0.3. Есть ещё альфа 3.1, но это альфа.

Архив содержит в себе Readme, примеры, сам фреймворк и ещё какие-то файлы, предназначение которых мне пока неизвестно :)

json framework for ios

Собственно сами файлы фреймворка находятся в папке Classes, которую и нужно перетащить в список файлов нашего проекта в XCode. Для удобства я переименовал после импорта папку в JSON.

json framework

В RootViewController.h мы импортируем фреймворк строкой:

#import "SBJson.h"

В RootViewController.h добавим такой код:

@interface RootViewController : UITableViewController  {
    NSMutableData *jsonData;
}
 
@property (nonatomic, retain) NSMutableData *jsonData;
 
@end

Мы объявляем свойство класса jsonData типа NSMutableData, в него мы будем складировать данные, которые нам вернёт запрос к API Twitter.

Строка property здесь нужна на случай, если мы хотим получить доступ к свойству jsonData вне нашего класса. nonatomic означает, что jsonData у нас не лочится (lock), то есть мы можем и получить, и изменить значение. Пишут, что nonatomic - работает быстрее, чем atomic. Atomic означает, что мы лочим значение. Насчет retain пишут: How the setter method will set the variable. Пока не понял, зачем это и как с этим работать, но без этой строки ничего не работает =).

Брать данные в JSON мы будет у Twitter'а. Благо у них для публичной ленты не нужно никаких авторизаций и токенов, достаточно послать запрос на определенный URL, для обкатки самое то.

Для начала - у нас есть класс RootViewController. В RootViewController.m разместим в viewDidLoad такой код:

@synthesize jsonData;
 
- (void)viewDidLoad {
    [super viewDidLoad];
    // создаем объект NSURL с адресом, на который будет идти запрос
    NSURL *url = [ NSURL URLWithString: @"http://twitter.com/statuses/public_timeline.json" ];
 
    // создаем объект NSURLRequest - запрос
    NSURLRequest *theRequest=[NSURLRequest requestWithURL:url
                                              cachePolicy:NSURLRequestUseProtocolCachePolicy
                                          timeoutInterval:60.0];
    // запускаем соединение
    NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
    if (theConnection) {
        self.jsonData = [NSMutableData data];
    } else {
        NSLog(@"Connection failed");
    }
    [theConnection release];
}

Для обработки соединения и данных нужно добавить ещё такой код:

/**
 * При получении новой порции данных добавляем их к уже полученным 
**/
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    [jsonData appendData:data];
}
 
/**
 * Если соединение не удалось - выводим в консоль сообщение об ошибке
**/
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    NSLog(@"%@", error);
}
 
/**
 * Когда все данные получены - разбираем их 
**/
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    // сохраняем полученные данные в строку result
    NSString *result = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
	
    // можно вывести в консоль и посмотреть - что мы получили
    NSLog( @"%@",result );

    // создаем объект с JSON-парсером
    SBJsonParser *jsonParser = [[SBJsonParser alloc] init];

    // Парсим строку данных result в объект класса NSArray (массив)
    NSArray *dataObject = [jsonParser objectWithString:result error:nil];

    // тут можно поставить Breakpoint

    // не забываем убить объекты
    [jsonParser release];
    [result release];
}

Если поставить Breakpoint ( CMD + \) в указанном выше месте ( см. "тут можно поставить Breakpoint" ), то можно посмотреть значения на этом этапе выполнения кода. Из скрина ниже видно, что полученная нами строка из Twitter распарсилась в объект dataObject типа NSArray, который внутри себя содержит 20 элементов, то есть данные о 20 твитах публичной ленты.

Работа  с JSON (парсинг) в Objective-C при разработке под iOS

После строки, где стоит Breakpoint, полученные данные уже можно как-то обрабатывать. Например, вывести в консоль полученные твиты в виде "Username - TweetText"

for ( NSDictionary *tweet in dataObject ) {
    NSLog(@"%@ - %@", [[tweet objectForKey:@"user"] objectForKey:@"screen_name"], [tweet objectForKey:@"text"] );
}

Работа  с JSON (парсинг) в Objective-C при разработке под iOS

Надеюсь, нигде не наврал и не ошибся. Поправкам/уточнениям только рад.

keyboard_return back