一、概述
UINavigationController
用來管理視圖控制器,在多視圖控制器中常用。它以棧的形式管理視圖控制器,管理視圖控制器個數理論上不受限制(實際受內存限制),push
和pop
方法來彈入彈出控制器,最多只能顯示一個視圖控制器,那就是處於棧頂的視圖控制器。
一般情況下,UINavigationController
最少管理一個控制器,即最少有一個根視圖控制器或者叫做棧底視圖控制器。當然也有例外,如果不給它添加視圖控制器也不會報錯,界面上也有視圖,因為UINavigationController
繼承自UIViewController
,也有自己的view,只不過默認情況下.view.backgroundColor
為nil,即透明的。
二、常用函數
- 使用
push
方法能將某個控制器壓入棧
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated;
- 使用
setViewControllers
一次壓入多個控制器vc1->vc2->vc3
,會顯示最后的控制器vc3(處於棧頂),代碼如下:
UINavigationController *nav = [[UINavigationController alloc] init]; window.rootViewController = nav; // 創建3個測試控制器 UIViewController *vc1 = [[UIViewController alloc] init]; vc1.view.backgroundColor = [UIColor blueColor]; UIViewController *vc2 = [[UIViewController alloc] init]; vc2.view.backgroundColor = [UIColor redColor]; UIViewController *vc3 = [[UIViewController alloc] init]; vc3.view.backgroundColor = [UIColor greenColor]; // 最終會顯示vc3 [nav setViewControllers:@[vc1,vc2,vc3] animated:YES];
- 使用pop方法可以移除棧頂控制器
當一個控制器被pop后,控制器內存就被釋放了(會調用deinit/dealloc函數):
- (UIViewController *)popViewControllerAnimated:(BOOL)animated;
一層一層的返回不方便,可以直接回到指定的控制器VCA(處與VCA與棧頂之間的控制器全被釋放),下面代碼執行后,VC_A處於棧頂:
- (NSArray *)popToViewController:VC_A animated:(BOOL)animated;
回到根控制器(棧底控制器):
-(NSArray *)popToRootViewControllerAnimated:(BOOL)animated;
- 獲取控制器
/// 當前管理的所有的控制器 @property(nonatomic,copy) NSArray<__kindof UIViewController *> *viewControllers; /// 棧頂控制器 @property(nullable, nonatomic,readonly,strong) UIViewController *topViewController; /// 當前可見的VC,可能是topViewController,也可能是當前topViewController present(modal)出來的VC,總而言之就是可見的VC @property(nullable, nonatomic,readonly,strong) UIViewController *visibleViewController;
注意,topViewController與visibleViewController大部分情況一樣,也有可能不同
三、導航條
UINavigationController
是做導航用的,具體的操作大部是由導航條來完成,導航條的使用就顯得很重要。導航條的內容由控制器的navigationItem
屬性決定。
1 navigationItem的屬性
一般使用self.navigationItem.對應屬性
來獲取屬性,或者設置屬性。或者使用self.navigationController
獲取到navigationController
,再通過navigationController
獲取到想要設置的viewController
- 中間的標題文字
@property(nullable, nonatomic,copy) NSString *title;
- 中間標題視圖
@property(nullable, nonatomic,strong) UIView *titleView;
- 導航欄附加解釋說明,如果設置了此字段,導航欄會高出30個點顯示此字段在
title
正上方
@property(nullable,nonatomic,copy) NSString *prompt;
- 自定義左上角的返回按鈕
/// 直接設置 @property(nullable, nonatomic,strong) UIBarButtonItem *leftBarButtonItem;
大部分情況下,我們需要指定左邊返回按鈕距離左邊框的距離,可以如下設定:
UIBarButtonItem *leftItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"gobackItem.png"] style:UIBarButtonItemStylePlain target:self action:@selector(backViewcontroller)]; UIBarButtonItem *fixedItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil]; // 設置邊框距離,個人習慣設為-16,可以根據需要調節 fixedItem.width = -16; self.navigationItem.leftBarButtonItems = @[fixedItem, leftItem];
下圖為設置邊框前后的差別:
- 子導航條后退按鈕,假設通過VC1
push
VC2,那么如果設置VC1.navigationItem.backBarButtonItem
就會顯示在VC2的左上角返回按鈕;如果再設置VC2.navigationItem.leftBarButtonItem
則會覆蓋VC1的設置;如果VC1和VC2都沒有設置,則會顯示默認的backBarButtonItem
。
@property(nullable,nonatomic,strong) UIBarButtonItem *backBarButtonItem;
- 自定義右上角的按鈕,或多個按鈕
@property(nullable, nonatomic,strong) UIBarButtonItem *rightBarButtonItem; /// 一次設置多個按鈕 @property(nullable,nonatomic,copy) NSArray<UIBarButtonItem *> *rightBarButtonItems;
2 設置navigationItem的字體格式
// 字體大小19,顏色為白色 [nav.navigationBar setTitleTextAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:19],NSForegroundColorAttributeName:[UIColor whiteColor]}];
四、UIToolBar
UINavigationController
自帶了一個工具欄,通過[self.navigationController setToolbarHidden:NO];
來顯示工具欄,工具欄中的內容可以通過viewController
的toolbarItems
來設置,顯示的順序和設置的NSArray中存放的順序一致,每一個UIBarButtonItem對象都可以設定點擊事件,可以使用系統提供的很多常用風格的對象,也可以根據需求進行自定義,下面舉例使用系統提供的樣式。
// 1 顯示工具條 [self.navigationController setToolbarHidden:NO]; // 2 創建四個UIBarButtonItem UIBarButtonItem *itemOne = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:nil action:nil]; UIBarButtonItem *itemTwo = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave target:nil action:nil]; UIBarButtonItem *itemThree = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:nil action:nil]; UIBarButtonItem *itemFour = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSearch target:nil action:nil]; // 間隙 UIBarButtonItem *flexibleItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]; // 3 添加到toolbarItems vc.toolbarItems = @[itemOne,flexibleItem,itemTwo,flexibleItem,itemThree,flexibleItem,itemFour];
效果如下:
另外,UIToolBar使用的比較少,大部分情況下而是使用另一個導航控制器UITabBarController
五 UINavigationBar、UINavigationItem、UIToolbar與UIBarButtonItem四者關系
NavigaitonBar
是導航欄,位於屏幕的上方,管理整個NavigationController
的navigationItem
,它類似navigationcontroller
一樣提供了一個棧來管理UINavigationItem
,在編程時,一般只設置每個控制器的navigationItem屬性- 一個導航控制器管理多個視圖控制器(多個視圖控制器共享一個導航控制器),而一個導航控制器只有一個
UINavigationBar
,被管理的多個視圖控制器共享這一個UINavigationBar
,只要一個視圖控制器改變了UINavigationBar
的屬性則影響是全局的。每個視圖控制器都會有屬於自己的UINavigationItem
,系統會以懶加載的方式創建一個UINavigationItem
顯示在UINavigationBar
中,改變UINavigationItem
只會在當前控制器起作用,不會影響其它控制器。 Toolbar
顯示在屏幕底部,是導航控制器的工具欄,一個導航控制器只有一個,在任何被管理的視圖控制器地方改變則會都改變。可以一次性添加多個UIBarButtonItem或按鈕(包裝成UIBarButtonItem后添加),有一個items數組屬性。UIBarButtonItem
是UINavigationItem
或者Toolbar
具體的一個按鈕。
六、UINavigationControllerDelegate
有兩個常用的方法
// 一般用於傳遞參數,或者做一些其它處理 - (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated; - (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated;