ПРОГРАММИРОВАНИЕ ПОД IPHONE, IPAD OBJECTIVE-C часть 2

11. UITabBarController

UITabBarController

 

UITabBarController — удобный инструмент для управление UIViewController-ми. Он используется во многих приложениях, но при этом в интернете существует мало примеров того как с ним работать. Этим примером я решил поправить сложившуюся ситуацию.

 

Создадим проект на основе шаблона Tabbed Application и назовем его TabBar (при создании проекта я снял галочку Use Storyboardподробнее об этом здесь). Здесь я сделаю некоторое отступление. В версии Xcode 4.1 весь функционал UITabBarControllerреализовывался интерактивно, то есть, в файле MainWindow.xib. Этот же функционал реализуется интерактивно в случае с отмеченой галочки Use Storyboard, но тогда нашу программу невозможно будет запустить на версии прошивки ниже 5.0. В нашем случае (без использования Storyboard) Xcode всю функциональность перенес в код, если заглянуть в файл AppDelegate.m, а точнее в метод application didFinishLaunchingWithOptions (этот метод вызывается в случае удачной загрузки приложения):

 

<code data-result="[object Object]">- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
    // Override point for customization after application launch.
    UIViewController *viewController1 = [[[FirstViewController alloc] initWithNibName:@"FirstViewController" 
                                                                               bundle:nil] autorelease];
    UIViewController *viewController2 = [[[SecondViewController alloc] initWithNibName:@"SecondViewController" 
                                                                                bundle:nil] autorelease];
    self.tabBarController = [[[UITabBarController alloc] init] autorelease];
    self.tabBarController.viewControllers = [NSArray arrayWithObjects:viewController1, viewController2, nil];
    self.window.rootViewController = self.tabBarController;
    [self.window makeKeyAndVisible];
    return YES;
}</code>

 

Что же такого происходит в этом метода? На самом деле все очень просто. В первй строке мы создаем окно (UIWindow), в приложении для iOS окно должно быть в программе только одно, тогда как для MacOS их может быть множество. В следующих двух строчках мы создаем объекты тех контроллеров, которые будут использоваться в нашем TabBarController, мы это делаем точно так же как в случае сконтроллером навигации. После того как контроллеры представления готовы — мы создаем сам UITabBarController и передаем в него массив тех контроллеров представления, которые только что инициализировали. Последние три строчки стандартны для большинства приложений iOS, в них мы указываем коренной контроллер для нашего единственного window, вызываем его метод makeKeyAndVisible и возвращаем логическое значение YES как знак того, что все прошло успешно.

 

Если сейчас запустить приложение на симуляторе — вы увидите следующую картинку:

 

 

Вы наверное уже заметили надписи и картинки на элементах нашего таб бара, тем более, эти картинки присутствуют в самом проекте. Но в вышеупомянутом методе ничего подобного мы не указывали. Дело в том, что установка картинки и надписи элемента UITabBarController происходит в самом контроллере представления, который мы передавали в массив. Если посмотреть в файл FirstViewController.m — можно найти следующий код:

 

<code data-result="[object Object]">- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        self.title = NSLocalizedString(@"First", @"First");
        self.tabBarItem.image = [UIImage imageNamed:@"first"];
    }
    return self;
}</code>

 

Метод initWithNibName вызывается в момент инициализации контроллера представления с xib-файла. Как раз в этот момент и происходит установка необходимых значений для TabBarController.

 

Мы разобрались как работает шаблон Xcode, теперь добавим в него наш контроллер представления. В первую очередь, добавим сам класс контроллера, я назвал его ThirdViewController. Теперь импортируем этот класс в AppDelegate.m и изменим метод didFinishLaunchingWithOptions:

 

<code data-result="[object Object]">- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
    UIViewController *viewController1 = [[[FirstViewController alloc] initWithNibName:@"FirstViewController" 
                                                                               bundle:nil] autorelease];
    UIViewController *viewController2 = [[[SecondViewController alloc] initWithNibName:@"SecondViewController" 
                                                                                bundle:nil] autorelease];
    UIViewController *viewController3 = [[[ThirdViewController alloc] initWithNibName:@"ThirdViewController" 
                                                                               bundle:nil] autorelease];

    UITabBarItem *item3 = [[[UITabBarItem alloc] initWithTitle:@"Third" image:nil tag:3] autorelease];
    viewController3.tabBarItem = item3;

    self.tabBarController = [[[UITabBarController alloc] init] autorelease];
    self.tabBarController.viewControllers = [NSArray arrayWithObjects:
                                             viewController1, 
                                             viewController2, 
                                             viewController3, nil];
    self.window.rootViewController = self.tabBarController;
    [self.window makeKeyAndVisible];
    return YES;
}</code>

 

Ничего особенного мы здесь не сделали, просто создали экземпляр только что добавленного контроллера и добавили его в массив TabBarController. Но в этом случае, имя табу и картинку мы задали с помощью класса UITabBarItem, а не в методе initWithNibName.

 

На последок хотелось бы разъяснить пару важных моментв. В отличии от Контроллера навигаций (UINavigationController) -UITabBarController загружает все контроллеры представления в память и держит их до конца работы программы. Отсюда следует, что метод viewDidLoad будет срабатывать только один раз (в момент загрузки приложения). То есть, если вы хотите выполнять какой-то код при переходе на один из контроллеров представления, которые содержатся в таб баре — следует этот код поместить в метод viewWillAppear или viewDidAppear (в зависимости от того, когда вы хотите выполнить нужный код).

 

<code data-result="[object Object]">- (void)viewWillAppear:(BOOL)animated {
    NSLog(@"Third");
}</code>

 

На последок, хотелось бы рассказать об таком полезном свойстве как badgeValue. Если метод viewDidLoad класса FirstViewControllerизменить следующим образом:

 

<code data-result="[object Object]">- (void)viewDidLoad
{
    [super viewDidLoad];

    self.tabBarItem.badgeValue = @"80 $";
}</code>

 

То в первом элементе таб-бара будет выведена надпись с указаным значением.

 

Исходный код проекта можно скачать здесь.