В связи с большой популярностью различных социальных сетей и микроблогов перед разработчиками приложений для iPhone часто возникает задача интеграции с ними. В этой статье будет показано, как простыми средствами встроить в приложение ленту последних записей из Твиттера.
Задача получения ленты записей из Твиттера делится на загрузку данных с сервера, их обработку и отображение. В качестве источника записей использовался формат JSON. Я продемонстрирую работу с JSON на примере одной из существующих библиотек, а также способы получения данных с удалённых серверов с помощью синхронных и асинхронных запросов.
Существует несколько свободных библиотек для работы с JSON на устройствах под управлением iOS. Из самых известных стоит отметить JSON Framework (именно эта библиотека была использована мной в процессе написания статьи) и TouchJSON. Эти библиотеки готовы для использования в проектах для iOS. Можно также воспользоваться другими библиотеками (например, легковесной cJSON), написав для них «обёртки» на Objective-C (такие обёртки по-английски называются wrapper).
Для получения последних записей из Твиттера не обязательно регистрировать своё приложение и получать ключ разработчика. У Твиттера есть открытый API, позволяющий получить ленту в виде объектов JSON. Для её получения надо всего лишь обратиться по адресу следующего вида:
http://twitter.com/statuses/user_timeline/USERNAME.json
где USERNAME — это имя пользователя, зарегистрированного в Твиттере. В случае, если такого пользователя не существует, придёт ответ в виде JSON, содержащий описание ошибки.
Синхронная загрузка данных
При использовании синхронных запросов мы отправляем запрос на сервер и ждём, пока от него придёт ответ. При этом выполнение потока, из которого была осуществлена отправка запроса, приостанавливается до прихода ответа. После того, как сервер ответил, и мы получили необходимые для работы данные, выполнение потока продолжается.
Синхронный запрос для получения ленты пользователя Твиттера отправляется следующим образом:
NSString *tweetsUrlString = [[NSString alloc] initWithFormat:@»http://twitter.com/statuses/user_timeline/%@.json», USERNAME]; NSURL *url = [[NSURL alloc] initWithString:tweetsUrlString]; [tweetsUrlString release]; NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url]; [url release]; NSURLResponse *response = nil; NSError *error = nil; NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
В результате выполнения этого метода в объект responseData запишется ответ от сервера. Объекты response (экземпляр NSURLResponse) и error (экземпляр NSError) будут содержать соответственно данные ответа (например, кодировку возвращаемых данных или тип MIME) и ошибку, если таковая возникла в процессе выполнения запроса.
После получения необходимых данных в виде объекта NSData можно отправить их на разбор в парсер JSON. Как уже было сказано в начале статьи, я воспользовался библиотекой JSON Framework. Данные, полученные от сервера, были преобразованы в NSString, потому что парсер при разборе строки может возвращать также описание ошибки, если она возникнет.
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding]; SBJsonParser *parser = [[SBJsonParser alloc] init]; NSError *jsonError; tweets = [[parser objectWithString:responseString error:&jsonError] retain]; [responseString release];
В результате выполнения этого кода в объекте tweets будет находиться массив из словарей (экземпляров NSDictionary), каждый из которых представляет одну запись в Twitter со всеми сопутствующими параметрами (такими, как текст твита, дата публикации, данные геолокации и т.п.). Этот массив можно обработать и вывести на экран. В демо-проекте к этой статье лента записей выводится в виде таблицы.
Асинхронная загрузка данных
Такой способ загрузки является более предпочтительным, так как процесс получения данных от удалённого сервера происходит в отдельном потоке и даёт больше возможностей для контроля за этим процессом. Создание соединения для асинхронного запроса происходит так:
NSString *tweetsUrlString = [[NSString alloc] initWithFormat:@»http://twitter.com/statuses/user_timeline/%@.json», USERNAME]; NSURL *url = [[NSURL alloc] initWithString:tweetsUrlString]; [tweetsUrlString release]; NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url]; [url release]; mConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
Параметр startImmediately:YES сообщает соединению, что загрузку можно начинать немедленно. Если передать в него значение NO, то отправку запроса придётся делать вручную:
mConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO]; [mConnection start];
Объект-делегат, переданный в параметре delegate, содержит следующие методы, которые будут вызываться в процессе работы соединения.
— (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
Этот метод вызовется в том случае, если соединение прервалось в результате возникновения ошибки. Из него можно вызвать тот объект, который ожидает получения данных, и, например, показать сообщение об ошибке на экране.
— (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
Этот метод вызывается после установления соединения. Из объекта response можно получить различные данные об ответе от сервера. Например, значение свойства expectedContentLength можно использовать для отрисовки прогресса загрузки.
— (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
Асинхронные запросы получают данные порциями, и при получении очередной порции будет вызываться этот метод. Поэтому перед запуском запроса необходимо создать экземпляр объекта NSMutableData, в который и будут дописываться полученные порции данных.
— (void)connectionDidFinishLoading:(NSURLConnection *)connection
Этот метод вызывается по завершении загрузки данных. Здесь можно обработать полученные данные, освободить ненужные объекты и передать управление объекту, который ожидает эти самые данные (в нашем случае это таблица, куда выводятся твиты).
В демонстрационном проекте к этой статье на экран выводятся твиты из ленты Артура Малосиева:
В проекте используется макрос TRACE для переопределения NSLog. Сделано это с целью отключения вывода отладочной информации при сборке цели Release. Макрос выглядит так:
#ifdef DEBUG #define TRACE(a, …) NSLog(a, ##__VA_ARGS__) #else #define TRACE(a, …) #endif
Для того, чтобы этот макрос заработал, и вывод NSLog отключался при сборке цели Release, необходимо в настройках проекта сделать следующее.
— переходим на вкладку Build
— в выпадающем списке Configuration выбираем Debug
— в строке поиска вводим текст cflags
— в пункте Other C Flags вводим следующий параметр: -DDEBUG
Этот параметр сообщит компилятору, что при сборке цели Debug будет определена переменная DEBUG, и все вхождения TRACE будут заменены на NSLog. При сборке цели Release все вхождения TRACE будут отброшены, и вывод отладочной информации производиться не будет.
Исходные коды библиотеки JSON Framework распространяются на условиях лицензии BSD и доступны на github.
Скачать исходные коды демонстрационного проекта к статье можно также скачать с github. Проект распространяется на условиях Public Domain, и любая его часть может быть использована в любых целях без указания моего авторства.
Источник: