В связи с большой популярностью различных социальных сетей и микроблогов перед разработчиками приложений для 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, содержащий описание ошибки.
Синхронная загрузка данных
При использовании синхронных запросов мы отправляем запрос на сервер и ждём, пока от него придёт ответ. При этом выполнение потока, из которого была осуществлена отправка запроса, приостанавливается до прихода ответа. После того, как сервер ответил, и мы получили необходимые для работы данные, выполнение потока продолжается.
Примечание: для большей наглядности я постарался избежать autorelease-объектов там, где это возможно.
Синхронный запрос для получения ленты пользователя Твиттера отправляется следующим образом:
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, и любая его часть может быть использована в любых целях без указания моего авторства.
13 комментариев
Форум →Сам разработкой пока не занимаюсь, но появление подобных статей создает практически отдельный раздел сайта. Так держать! Думаю в будущем Никита сделает многое для айфонсру)
@TauruS_iPhone4_now, +1
Отличная статья, полностью поддерживаю идею отдельного раздела.
Никита, спасибо!
ув.разработчики загляните сюда http://www.iphones.ru/forum/index.php?showtopic=77833
нужна помощь
Никита, вижу ты уже бывалый разработчик.
А под мак писать умеешь?
у меня вот вопрос один
http://*****
Запрещено давать ссылки на сторонние ресурсы. Кроме того, есть раздел разработчиков на форуме.
никто не отвечает пока
может ты знаешь)
@Rusik, пипец вы злые какие
ну в жопу ваш форум
он нифига неудобный
@Rusik, Под Мак писать не умею.
@Rusik, а тут никакой Голубиной книги с тайными знаниями не надо, все по уставу и инструкции в три строчки.
В windowDidLoad добавляем:
// получаем root-control
NSView* root = [[[self window] contentView] superview];
// определяем его размер
NSRect rc = [root bounds];
// кнопку размером 10х10 помещаем в заголовок с коорд 30,0
// а что бы было красиво, выясняйте размер заголовка
rc.origin.x += 30; rc.size.width = 10;
rc.origin.y = rc.size.height – 10; rc.size.height = 10;
// создаем кнопку
NSButton butt = [[NSButton alloc] initWithFrame:rc];
// добавляем ее в root-control
[root addSubview:butt];
// обработку событий добавляем к кнопке с помощью
// setTarget и setAction
Извиняюсь, это ответ Novikoff-у, а не Rusik
Помогите мне тоже кто нибудь
вот вопрос
http://www.iphones.ru/forum/index.php?showtopic=77843
Вы лучше здесь сформулируйте вопрос, а то там по ссылке надо регистрироваться, и письмо с регистрацией не высылается. Но сам по себе вопрос “Как работает NSUndoManager” очень странный – в документации вообще-то все есть.
@Afx40, эт блин
я думал вопросы всем без регистрации показываются
ну вот собственно вопрос (там подсветка синтаксиса, все как надо)
http://pastie.org/1800936
Модераторам:
Только вот не надо эту ссылку стирать и говорить, что это ссылка на сторонний ресурс. Там текст только
@Rusik, можете уже начинать нервно смеяться – у Вас ВСЕ ПРАВИЛЬНО. Не найдя ошибки, я специально проверил – создал doc-based app, дословно перенес туда Ваш код. Все превосходно работает (Xcode 3.2.5). Могу высказать только одно предположение – пока Вы экспериментировали, что-то сломали в другом месте. Попробуйте создать проект заново.
P.S. Кстати, Вы там ничего не удаляли из сгенерированного текста, я надеюсь, а только добавляли свой текст?
Нашли орфографическую ошибку в новости?
Выделите ее мышью и нажмите Ctrl+Enter.Как узнать, какие приложения потребляют трафик ночью
Как сохранять настройки в стандартном приложении Камера на iPhone
Как заново привязать номер телефона к App Store после неудачной оплаты
Как найти Apple Watch при помощи iPhone. Есть два способа
Как на Mac принимать файлы по AirDrop, если пользователя нет в контактах
Как восстановить перезаписанный файл на Mac
Как использовать любое видео в качестве заставки на Mac
Почему iPhone сам запускает приложения