28 ноября 2010 г.

Кастомные заголовки и подписи в секциях UITableView

Иногда необходимо что б в заголовке секции таблицы UITableView отображался не только текст, но и картинка, или может даже кнопка. Компонента UITableView позволяет не только задавать текстовую строку как заголовок к каждой секции но и устанавливать свое UIView как элемент заголовка.

UITableView поддерживает отсылку событий по двум протоколам UITableViewDataSource и UITableViewDelegate. Первый отвечает за получение данных которые отображаются в компоненте, второй за их внешний вид. В протоколе UITableViewDataSource есть методы – tableView:titleForHeaderInSection: и – tableView:titleForFooterInSection: которые должны возвращать строки заголовка и подписи для каждой секции в таблице. Но в протоколе UITableViewDelegate можно реализовать методы – tableView:viewForHeaderInSection: и – tableView:heightForHeaderInSection: для установки вашего вью на заголовок секции (методы – tableView:viewForFooterInSection: и – tableView:heightForFooterInSection: для подписи секции)

Реализуем простой пример использования (скачать можно отсюда)

У нас есть UIViewController на котором находится UITableView. Создаем вью которое будем использовать как заголовок секции таблицы.

  1.   CGRect rct;
  2.   headerView = [[UIView alloc] initWithFrame:CGRectZero];
  3.   UIImage *img = [UIImage imageNamed:@"apple.png"];
  4.   UIImageView *tmpImgView = [[UIImageView alloc] initWithImage:img];
  5.   rct = CGRectMake(screenRect.size.width*.05, 0.0, img.size.width, img.size.height);
  6.   tmpImgView.frame = rct;
  7.   [headerView addSubview:tmpImgView];
  8.   rct.origin.x = 0.0;
  9.   rct.size = CGSizeMake(screenRect.size.width, rct.size.height);
  10.   headerView.frame = rct;
  11.   [tmpImgView release];


тут headerView - имеет тип UIView, его то мы и будем отображать в таблице.

А теперь опишем функции отображение этого вью как заголовка первой секции таблицы:

  1. - (UIView *) tableView:(UITableView *) tableView viewForHeaderInSection:(NSInteger) section
  2. {
  3.   if (section==0)
  4.   {
  5.     return headerView;
  6.   }
  7.   return nil;
  8. }
  9. - (CGFloat) tableView:(UITableView *) tableView heightForHeaderInSection:(NSInteger) section
  10. {
  11.   if (section==0)
  12.   {
  13.     return headerView.frame.size.height;
  14.   }
  15.   return 0.0;
  16. }


В первой функции мы возвращаем вью которое должно отображаться в таблице, во второй - высоту этого вью.

Так-же в компоненте UITableView можно использовать свойства tableHeaderView  и tableFooterView  для задания вью как заголовка и подписи всей таблицы.

20 ноября 2010 г.

Изменение шрифта в компоненте UISegmentedControl

Если вам не хватает стандартных стилей компоненты UISegmentedControl, то изменение шрифта надписей, это то место, которое не описано в iOS Reference Library. Код для изменения шрифта в компоненте UISegmentedControl взят с форума www.iphonedevsdk.com:

  1. void changeUISegmentFont(UIView* aView)
  2. {
  3.   NSString* typeName = [[aView class] className];
  4.   if ([typeName compare:@"UISegmentLabel" options:NSLiteralSearch] == NSOrderedSame)
  5.   {
  6.     UILabel* label = (UILabel*)aView;
  7.     [label setTextAlignment:UITextAlignmentCenter];
  8.     [label setFont:[UIFont boldSystemFontOfSize:14]];
  9.   }
  10.   NSArray* subs = [aView subviews];
  11.   NSEnumerator* iter = [subs objectEnumerator];
  12.   UIView* subView;
  13.   while (subView = [iter nextObject])
  14.   {
  15.     changeUISegmentFont(subView);
  16.   }
  17. }


параметром этой функции и есть экземпляр обьекта UISegmentedControl.

16 ноября 2010 г.

Пишем бота для twitter на python

Нашел все-таки время разобраться с OAuth авторизацией. Этот позволяет социальным сервисам интегрироваться между собой обеспечивая безопасный метод обмена информацией. Для интересующихся еще ссылка.

Приступим к написанию бота. Первое, что необходимо сделать - зарегистрировать приложение на сервисе twitter. В результате получаем Consumer key и Consumer secret.



Теперь разберем сам скрипт. Он написан на основе библиотеки oauth-python-twitter2, задача: фолловить и анфолловить случайных пользователей. Скрипт можно скачать здесь.

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. from oauth import oauth
  4. from oauthtwitter import OAuthApi
  5. import sys
  6. import os
  7. twitter = None
  8. consumerKey = ''
  9. consumerSecret = ''
  10. def auth():
  11.   authToken = None
  12.   authSecret = None
  13.   if os.path.exists('/tmp/twitter.tmp'):
  14.     f = open('/tmp/twitter.tmp', 'r')
  15.     authToken = f.readline().strip()
  16.     authSecret = f.readline().strip()
  17.     print "oauth_token: " + authToken
  18.     print "oauth_token_secret: " + authSecret
  19.     f.close()
  20.   needAuth = True
  21.   if authToken!=None and authSecret!=None:
  22.     twitter = OAuthApi(consumerKey, consumerSecret, authToken, authSecret)
  23.     if twitter.autorized():
  24.       needAuth = False
  25.   if needAuth:
  26.     twitter = OAuthApi(consumerKey, consumerSecret)
  27.     temp_credentials = twitter.getRequestToken()
  28.     print temp_credentials
  29.     print twitter.getAuthorizationURL(temp_credentials)
  30.     oauth_verifier = raw_input('What is the PIN? ')
  31.     access_token = twitter.getAccessToken(temp_credentials, oauth_verifier)
  32.     print access_token
  33.     print("oauth_token: " + access_token['oauth_token'])
  34.     print("oauth_token_secret: " + access_token['oauth_token_secret'])
  35.     f = open('/tmp/twitter.tmp', 'w')
  36.     f.write('%s\n%s'%(access_token['oauth_token'], access_token['oauth_token_secret']))
  37.     f.close()
  38.     twitter = OAuthApi(consumerKey, consumerSecret, access_token['oauth_token'], access_token['oauth_token_secret'])
  39.   return twitter
  40. def unfollow():
  41.   friends = twitter.GetFriendsIDs()
  42.   for i in range(min(len(friends),30)):
  43.     twitter.UnfollowUser(friends[i])
  44. def follow(query):
  45.   users = twitter.searchByQuery(query)
  46.   count = min(30, len(users))
  47.   for user in users:
  48.     print user['id']
  49.     twitter.FollowUser(user['id'])
  50. if __name__=='__main__':
  51.   if len(sys.argv)<2:
  52.     print "Usage: %s <mode>"%sys.argv[0]
  53.     print "Mode:"
  54.     print "  follow   - find and follow by twitter users"
  55.     print "  unfollow - unfollow twitter users"
  56.     print ""
  57.     sys.exit(0)
  58.   if sys.argv[1]=='unfollow':
  59.     twitter = auth()
  60.     unfollow()
  61.   elif sys.argv[1]=='follow':
  62.     twitter = auth()
  63.     follow('twitter')


самое интересное в скрипте, метод auth. В файле /tmp/twitter.tmp я храню токен авторизации пользователя. Если этот токен не существует или не принимается пользователем, то вывожу на экран урл авторизации и жду пока пользователь авторизуеться в твиттере и введет PIN в приложение. По этому пину и получаем токен авторизации который и сохраняем в файл /tmp/twitter.tmp до следующего запуска скрипта.

Методы follow вызывает метод search твиттера и фолловит найденых пользователей. Метод unfollow берет список фолловеров и отписываеться от некоторых из них.

2 ноября 2010 г.

Ссылка на AppStore reviews приложения из приложения

В магазине приложений AppStore сделано так, что боольшинство оценок которыми оценивают ваше приложение появляется при удалении приложения с устройсва. А пользователь удаляет приложение если оно ему не понравилось, т.е. большинство оценок приложению достаются низкие.

Можно попробовать решить сделав переход из вашего приложения на страничку написания ревью к вашему приложению. Как это Вы реализуете: ссылкой в "О программе" или алертом при каждом запуске приложения с просьбой оценить приложение - не важно. Я здесь привожу лишь код сотавления урл-аддреса и открытие его:

  1. NSString *str = @"itms-apps://ax.itunes.apple.com/WebObjects/MZStore.woa";
  2. str = [NSString stringWithFormat:@"%@/wa/viewContentsUserReviews?", str];
  3. str = [NSString stringWithFormat:@"%@type=Purple+Software&id=", str];
  4. // Здесь добавляем AppleID вашего приложения из iTunesConnect
  5. str = [NSString stringWithFormat:@"%@348529788", str];
  6. [[UIApplication sharedApplication] openURL:[NSURL URLWithString:str]];


В результате переходим в приложение AppStore на сраничку Write review приложения (не забудьте поменять id в коде)



Спасибо memention за инструкцию.

Добавление файлов в библиотеку iTunes без копирования файлов

Известно, что при добавлении файлов в iTunes приложение копирует файлы в свою библиотеку. Мне не хочется держать по нескольку копий больших видеофайлов на жестком диске.

Решение простое - добавлять в iTunes не сами файлы а ссылки на них. Для этого, перетаскиваем с Finder при нажатой клавише Option нужный файл или папку. Вуаля, в библиотеку добавилась ссылка на файл.

1 ноября 2010 г.

Локализация даты/времени

Формат даты/времени не зависит от текущего языка на вашем устройстве. А зависит от региональных настроек:



Для отображения даты/времени я использую UIDatePicker который от региональных настроек устройства отображает дату и время корректно. Если же мне нужна текстовая строка с локализованной датой/временем (для вывода на экран например), то я использую класс NSDateFormatter для получения строки. У обоих классов есть так-же метод setLocale: в котором можно жестко указать в каком региональном формате отображать дату/время.

См. также:
1. Локализация строк в Xcode