В связи с большой популярностью различных социальных сетей и микроблогов перед разработчиками приложений для 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.Как на iPad завершать приложения при помощи клавиатуры
Как запретить удалять файлы с рабочего стола Mac
Как в iOS 16 перенести eSIM с одного iPhone на другой
Как управлять Apple TV 4 с iPhone или iPad
Почему не получается удалять приложения на iPhone
Как отвязать банковскую карту от Apple ID
Как быстро скачать фото из iCloud на чужом компьютере
Как произвести повторную калибровку аккумулятора iPhone в iOS 14.5