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 твитах публичной ленты.

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

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


 

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

keyboard_return back