Thursday, December 27, 2012

Использование UINavigationController вместе с UITabBarController




25 октября 2011 в 01:33
Появилась нужна использовать в проекте и UINavigationController, и UITabBarController одновременно. Два способа как это сделать.
Создадим пустой проект. Прописывать контроллеры будем вручную. Итак, у нас есть AppDelegate.h и AppDelegate.m. 
Способ 1. UINavigationController внутри UITabBarController. (от @vox_humana)
В этом способе в приложении всегда есть Tab Bar, он всегда виден и между табами всегда можно переключаться. Внутри одного из табов (или можно сделать во всех) есть вид с UINavigationController, в котором можно делать перемещение между видами с помощью push и pop.
Создадим два новый файла типа UIViewController subclass (с галкой with XIB for user interface). Назовём их, скажем, FirstViewController и SecondViewController. Это будут два наших вида, которые будут выводиться в двух табах.
Наш AppDelegate.h в пустом проекте выглядит так:
1234567
  
#import <UIKit/UIKit.h>
  
  
@interface AppDelegate : UIResponder <UIApplicationDelegate>
  
@property (strong, nonatomic) UIWindow *window;
  
@end
view rawgistfile1.mThis Gist brought to you by GitHub.

Нам нужно добавить новую @property c UITabBarController:
123456789
  
#import <UIKit/UIKit.h>
  
  
@interface AppDelegate : UIResponder <UIApplicationDelegate>
  
@property (strong, nonatomic) UIWindow *window;
  
@property (strong, nonatomic) UITabBarController *tabBarController;
  
@end
view rawgistfile1.mThis Gist brought to you by GitHub.

Далее идём в AppDelegate.m. Здесь нужно импортировать созданные FirstViewController и SecondViewController, а также сделать @synthesize для табов:
12345678
  
#import "AppDelegate.h"
  
#import "FirstViewController.h"
  
#import "SecondViewController.h"
  
  
@implementation AppDelegate
  
  
@synthesize window = _window;
@synthesize tabBarController = _tabBarController;
view rawgistfile1.mThis Gist brought to you by GitHub.

Внутри метода didFinishLaunchingWithOptions прописываем следующее:
123456789101112131415161718192021222324
  
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  
// создаём окно для приложения по размеру экрана
  
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
  
// создаём два экземпляра UIViewController
  
UIViewController *viewController1, *viewController2;
  
// первый вид инициализируем с интерфейсом нашего первого контроллера
  
viewController1 = [[UINavigationController alloc] initWithRootViewController:[[FirstViewController alloc] initWithNibName:@"FirstViewController" bundle:nil]];
  
// второй вид инициализируем с интерфейсом нашего второго контроллера
  
viewController2 = [[SecondViewController alloc] initWithNibName:@"SecondViewController" bundle:nil];
  
// подключаем наши виды к таб-бару
  
self.tabBarController = [[UITabBarController alloc] init];
self.tabBarController.viewControllers = [NSArray arrayWithObjects:viewController1, viewController2, nil];
  
// как основной контроллер приложению ставим tabBarController
  
self.window.rootViewController = self.tabBarController;
  
[self.window makeKeyAndVisible];
return YES;
  
}
view rawgistfile1.mThis Gist brought to you by GitHub.

Теперь при запуске у нас появится таб-бар внизу экрана. В каждом табе будет по виду. Первый вид (viewController1) будет иметь в себе UINavigationController, что позволит нам делать push и pop видов. Для примера добавим ещё один UIViewController subclass (с галкой with XIB for user interface). Назовём его MyViewController. Таким образом у нас уже будет 3 UIViewController в проекте:
Поскольку у нас viewController1 (он же FirstViewController) содержит в себе UINavigationController, то добавим в него какое-нибудь действие, чтобы перейти в наш контроллер. Сначала в начале FirstViewController.m сделаем #import "DetailViewController.h", затем добавим метод:
1234
  
- (IBAction)pushToMyController:(id)sender {
MyViewController * childControl = [[MyViewController alloc] initWithNibName:@"MyViewController" bundle:nil];
[[self navigationController] pushViewController:childControl animated:YES];
}
view rawgistfile1.mThis Gist brought to you by GitHub.
Ну и само собой не забудем объявить его в FirstViewController.h :
- (IBAction)pushToMyController:(id)sender;
 Добавим в FirstViewController.xib кнопку и свяжем её через Connection Inspector с нашим action:
Готово. Можно запускать. На выходе получаем вот такой результат:
По такому принципу сделно приложение Dropbox для iPhone, например. Скачать готовый пример.

Способ 2. UITabBarController внутри UINavigationController(с помощью @Krivoblotsky)
Начинаем с того, что создаём RootViewController. Ему нужно создать @property:
@property (nonatomic, retain) IBOutlet UITabBarController *tabBarController;
Добавить в xib-файл UITabBarController, связать его в Connections Inspector. Создаём два вида в проекте - FirstViewController и SecondViewController, для UITabBarController, что внутри RootViewController.xib привязываем табы к этим видам. 
Приведу начало файла AppDelegate.m:
123456789101112131415161718192021222324
  
#import "AppDelegate.h"
  
#import "RootViewController.h"
  
  
@implementation AppDelegate
  
  
@synthesize window = _window;
@synthesize viewController = _viewController;
  
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  
// создаём окно
  
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
  
// создаём главный контроллер
  
self.viewController = [[RootViewController alloc] initWithNibName:@"RootViewController" bundle:nil];
  
// создаём UINavigationController
  
navigationController = [[UINavigationController alloc] initWithRootViewController:self.viewController];
  
// назначаем главным контроллером UINavigationController
  
self.window.rootViewController = navigationController;
[self.window makeKeyAndVisible];
  
return YES;
  
}
view rawgistfile1.mThis Gist brought to you by GitHub.
Общая суть в том, что self.window.rootViewController - это UINavigationController. У приложения есть RootViewController со своим xib. Его можно оставить пустым, но ему нужно прописать @property:
@property (nonatomic, retain) IBOutlet UITabBarController *tabBarController;
Когда вид RootViewController загружается - мы сразу делаем push в наш tabBarController. Таким образом первое, что видно при запуске - это табы и верхнюю панель с кнопкой назад, которую в этом месте можно скрыть и показывать только дальше где-то. 
Главный плюс - внутри видов, которые грузятся внутри UITabBarController - можно в коде делать перемещение основного экрана в другие виды и возвращаться обратно. Видео:

По такому принципу сделано приложение ВКонтакте для iPhone. Реализовано в моём примере, пожалуй, не идеально, при желании можно допилить, но работает. Скачать пример.
На будущее пригодится, заодно сам ещё раз всё проделал и закрепил.

No comments:

Post a Comment