|
Май
24
|
В этом уроке я покажу, как создать приложение “UITabBarController” посредством исключительно кода. Единственная его задача — переключаться между двумя контроллерами табличного представления, но это даст основу для создания приложений с вкладками и пример выполнения контроллерами различных задач. Слева показано (нажмите для увеличения), как будет выглядеть готовое приложение (за изображения для кнопок на вкладках отдельное спасибо Apple Computer — они взяты из тестового приложения Elements).
Немного о том, почему вместо редактора Interface Builder (IB) все будет выполняться программированием. Во-первых, я не в восторге от IB: многое в нем остается “за кадром”, а отладка приложений бывает затруднительной. От работы с редактором не зарекаюсь, но предпочитаю сначала справляться без него, а IB при необходимости подключать на последующих этапах — так картина происходящего намного яснее.
Перед началом несколько слов о контроллерах “UITabBarControllers“. Принцип работы заключается в предоставлении им массива контроллеров представлений (табличных, навигационных и пр.) с назначением этого массива свойством “viewControllers” для объекта “UITabBarControllers“. Все достаточно просто, но есть ряд подводных камней, из-за которых программа не запустится или будет аварийно завершать работу. Те, кто прочел “View Controller Guide for iPhone OS” от Apple, знают, что объект “UITabBarController” правильно создавать посредством приведенного ниже кода:
1 | tabBarController = [[UITabBarController alloc] initWithNibName:nil bundle:nil]; |
Однако это НЕВЕРНО. Вместо такого подхода достаточно следующего:
1 | tabBarController = [[UITabBarController alloc] init]; |
Кстати, судя по форумам, с этой проблемой сталкиваются достаточно часто.
Итак, приступим. Предполагается, что вы уже работали с XCode и хотя бы на базовом уровне знакомы с программированием на iPhone и языком Objective-C.
1) Откройте XCode и выполните “File > New Project > Window-based Application” (в разделе “iPhone OS Application“). Поскольку все будет делаться вручную, нет необходимости в том, чтобы XCode занимался за нас классами контроллеров представления и пр. Присвойте проекту любое имя на выбор. Свой я назвал “SimpleTabBar“.
2) Теперь создадим два контроллера табличного представления, которые будут выводиться при щелчке на любой из вкладок панели. Удерживая нажатой клавишу <Control>, щелкните правой кнопкой на папке “Classes” и выполните “Add > New File“. После “iPhone OS > Cocoa Touch Classes” выберите подкласс “UITableViewController” и подтвердите кнопкой “Next“. Присвойте классу имя типа “RootViewController.m” (не забудьте создать при этом и заголовочный файл). Точно так же создайте второй контроллер представления, назвав его, например, “SecondViewController.m“.
3) Теперь у вас должно быть три класса: “SimpleTabBarAppDelegate“, “RootViewController” и “SecondViewController“. В разделе интерфейса “SimpleTabBarAppDelegate” добавьте две следующих переменных экземпляра (”window” там уже есть). Объявите их свойствами, чтобы код принял следующий вид:
1 2 3 4 5 6 | @interface SimpleTabBarAppDelegate : NSObject { UIWindow *window; UITabBarController *tabBarController; } @property (nonatomic, retain) UITabBarController *tabBarController; @property (nonatomic, retain) UIWindow *window; |
Возможно, вы уже догадались, что объект “tabBarController” будет использован для создания контроллера панели вкладок. В моем примере в декларации свойств окна перед “UIWindow” XCode вставляет также тип IBOutlet, но это необязательно, поэтому я его удалил.
4) Теперь перейдите к разделу реализации “SimpleTabBarAppDelegate“, куда мы внесем код для добавления к “tabBarController” массива контроллеров табличного вида (”RootViewController” и “SecondViewController“). Разобьем эту операцию на отдельные этапы. Для начала добавьте заголовочные файлы для двух классов контроллеров представления, поскольку мы будем создавать эти классы из “SimpleTabBarAppDelegate“. Прямо под строкой с выражением “#import “SimpleTabBarAppDelegate“ вставьте две строки кода:
1 2 | #import "RootViewController.h" #import "SecondViewController.h" |
Прямо под “@synthesize window;” добавьте еще и следующую строку:
1 | @synthesize tabBarController; |
5) В методе “applicationDidFinishLaunching” сначала создадим локальную версию для “UINavigationController“, в которой будут обитать оба наших контроллера “UITableViewController“. Благодаря этому, пользователям будет удобнее перемещаться по таблицам приложения. Кроме того, создадим объект “UIWindow“. (В этом уроке я не буду подробно рассматривать процессы, имеющие место при создании объекта “UIWindow” — много полезного по этой теме найдете на сайте Apple’s iPhone Dev.)
1 2 3 4 5 6 | // настройте локальный контроллер навигации, который будет повторно использоваться для каждого контроллера представления UINavigationController *localNavigationController; // настройте окно window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; [window setBackgroundColor:[UIColor blackColor]]; |
6) Если помните, выше уже говорилось о том, что класс “UITabBarController” является местом хранения массива контроллеров представления. Чтобы получить такой результат, создадим объект контроллера панели вкладок и массив со всеми контроллерами представления.
1 2 3 | // создайте контроллер панели вкладок и массив для контроллеров представления tabBarController = [[UITabBarController alloc] init]; NSMutableArray *localControllersArray = [[NSMutableArray alloc] initWithCapacity:2]; |
Отредактируйте “initWithCapacity” с учетом количества вкладок (в данном случае, их две).
7) Пора создать собственно контроллеры представления и добавить их в массив. Сначала займемся корневым контроллером. Обратите внимание: создав контроллер, я добавляю его к контроллерам навигации в качестве “корневого”.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | // настройте первый контроллер представления (Root view controller) RootViewController *myViewController; myViewController = [[RootViewController alloc] initWithTabBar]; // создайте контроллер навигации и добавьте в качестве первого представления корневой контроллер localNavigationController = [[UINavigationController alloc] initWithRootViewController:myViewController]; // добавьте новый контроллер навигации (с корневым контроллером представления внутри) // к массиву контроллеров [localControllersArray addObject:localNavigationController]; // освободите, поскольку на этом пока все [localNavigationController release]; [myViewController release]; |
На метод “initWithTabBar” пока не обращайте внимания. Это частный метод инициализации, который я опишу ниже.
8) Те же операции проделайте для второго контроллера представления (SecondViewController):
1 2 3 4 5 6 7 | // настройте второй контроллер представления по аналогии с первым SecondViewController *secondViewController; secondViewController = [[SecondViewController alloc] initWithTabBar]; localNavigationController = [[UINavigationController alloc] initWithRootViewController:secondViewController]; [localControllersArray addObject:localNavigationController]; [localNavigationController release]; [secondViewController release]; |
9) Теперь давайте загрузим наш контроллер панели вкладок с массивом контроллеров представления.
1 2 3 4 5 6 7 8 9 10 11 | // загружаем контроллер панели вкладок с контроллерами представления tabBarController.viewControllers = localControllersArray; // освобождаем массив, поскольку он уже есть у контроллера панели вкладок [localControllersArray release]; // добавляем "tabBarController" в окно в качестве подпредставления [window addSubview:tabBarController.view]; // последней строкой отображаем окно (и контроллер панели вкладок) [window makeKeyAndVisible]; |
10) Попрактикуйтесь в правильном управлении памятью, освободив окно и “tabBarController”.
1 2 3 4 5 | - (void)dealloc { [tabBarController release]; [window release]; [super dealloc]; } |
11) ОК - львиная доля работы сделана. Осталось внести небольшие изменения в каждый из контроллеров, чтобы приложение после компиляции заработало! Для каждого из контроллеров представления мы изменим заголовки, чтобы на экран выводилось “Tab1″ вместо “Tab2“. Я не буду приводить для них код: он останется тем же самым за исключением отредактированной текстовой метки. Для начала опишем частный метод инициализации (”initWithTabBar“) в разделе интерфейса файла “RootViewController.h“. Выглядит это так:
1 2 3 4 5 6 7 | @interface RootViewController : UITableViewController { } -(id)initWithTabBar; @end |
12) Переходим к разделу реализации, где вставим соответствующий код частного метода инициализации. Заметьте, что эта задача разрешима разными способами. Чтобы назначить стиль для таблицы, достаточно вставить код в имеющийся метод “initWithStyle“. Я сделал это по-другому специально, чтобы продемонстрировать в действии частный метод инициализации.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | -(id) initWithTabBar { if ([self init]) { //метка на кнопке собственно вкладки self.title = @"Tab1"; //добавьте к проекту любое изображение self.tabBarItem.image = [UIImage imageNamed:@"name_gray.png"]; // назначьте длинное имя, выводимое сверху в панели навигации self.navigationItem.title=@"Nav Title"; } return self; } |
Думаю, все понятно из комментариев.
13) Теперь проделайте то же самое в классе “SecondViewController“, изменив заголовки на “Tab2” и т.д.
14) Щелкнув на кнопке “Compile and Go“, просмотрите результаты работы.
Теперь при желании можно добавить любое количество вкладок и кнопок. Просто создайте нужное число контроллеров представления и для каждого повторите описанные шаги в классе “AppDelegate“. При инициализации не забудьте изменить размер множества!


Ноябрь 24th, 2009 at 09:12
неужели у кого-то заработало ?
у меня (SDK 3.1.2, xCode 3.1.4) пока не удалил строчки
// настройте окно
window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[window setBackgroundColor:[UIColor blackColor]];
то ничего приличного на экране не показывалось. Да и в оригинале их нету!! Откуда вы их сюда притянули ?