导航控制器(NavigationController)的基本属性及生命周期

一、概述
UINavigationController用来管理视图控制器,在多视图控制器中常用。它以栈的形式管理视图控制器,管理视图控制器个数理论上不受限制(实际受内存限制),push和pop方法来弹入弹出控制器,最多只能显示一个视图控制器,那就是处于栈顶的视图控制器。

一般情况下,UINavigationController最少管理一个控制器,即最少有一个根视图控制器或者叫做栈底视图控制器。当然也有例外,如果不给它添加视图控制器也不会报错,界面上也有视图,因为UINavigationController继承自UIViewController,也有自己的view,只不过默认情况下.view.backgroundColor为nil,即透明的。
二、常见属性和方法

- (instancetype)initWithRootViewController:(UIViewController *)rootViewController; 

以一个viewController为栈底,实例化一个navigation viewcontroller

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated; 

展示一个viewcontroller,压栈操作(可以有动画效果)。

- (nullableUIViewController *)popViewControllerAnimated:(BOOL)animated;

结束并隐藏一个viewcontroller(dealloc),出栈操作(可以有动画效果),返回出栈的viewcontroller

- (nullableNSArray<__kindofUIViewController *> *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated; 

结束并隐藏 在栈中位于一个特殊的viewcontroller之前所有的viewcontroller,并返回

- (nullableNSArray<__kindofUIViewController *> *)popToRootViewControllerAnimated:(BOOL)animated;

出栈到根viewcontroller

@property(nullable,nonatomic,readonly,strong) UIViewController *topViewController; 

栈顶viewcontroller

@property(nullable,nonatomic,readonly,strong) UIViewController *visibleViewController; 

如果模态viewcontroller存在,返回模态viewcontroller,否则栈顶viewcontroller

@property(nonatomic,copy) NSArray<__kindofUIViewController *> *viewControllers; 

当前栈中的元素

- (void)setViewControllers:(NSArray<UIViewController *> *)viewControllers animated:(BOOL)animated NS_AVAILABLE_IOS(3_0); 

设置栈中的元素,animated=yes,根据当前的栈顶viewcontroller在不在这个viewcontroller数组中,模拟一次push和pop的动画。这就相当于对当前的栈进行了一次整体的刷新

下面的bar属性主要是用来显示顶部的导航栏以及底部的工具栏

@property(nonatomic,getter=isNavigationBarHidden)BOOLnavigationBarHidden;
- (void)setNavigationBarHidden:(BOOL)hidden animated:(BOOL)animated; 
@property(nonatomic,readonly) UINavigationBar *navigationBar; 
@property(nonatomic,getter=isToolbarHidden)BOOLtoolbarHidden NS_AVAILABLE_IOS(3_0) __TVOS_PROHIBITED;
- (void)setToolbarHidden:(BOOL)hidden animated:(BOOL)animated NS_AVAILABLE_IOS(3_0) __TVOS_PROHIBITED; 
@property(null_resettable,nonatomic,readonly) UIToolbar *toolbar NS_AVAILABLE_IOS(3_0) __TVOS_PROHIBITED;// 

delegate,可以在压栈出栈操作中,设置一些动画,以及一些额外的操作
@property(nullable,nonatomic,weak)id<UINavigationControllerDelegate> delegate;

这里需要说一下visibleViewController和topViewController:topViewController永远代表着栈顶元素;visibleViewController代表着当前显示的那个vc,这个vc可能是top vc,也有可能是top vc 展示出来的vc。

UINavigationItem以及其与UINavigationBar的关系:
在前面的简介之中,提到UINavigationController管理着一个UIViewController的栈和一个UINavigationBar。其实,一个UINavigationController的实例对应一个UINavigationBar的实例,而一个UINavigationBar的实例同样管理着一个栈,这个栈中的元素就是UINavigationItem。所以,既然一个navigationController对应一个navigationBar,可以推断到UINavigationController的栈和UINavigationBar的栈也是对应的,而两个栈里元素也是一一对应,也就是一个UIViewController的实例也对应着一个UINavigationItem的实例(如果不对应,系统会报异常情况)。在navigationController进行push和pop的同时,navigationBar也在同时做相应的push和pop 。在官方的API中,在UINavigationController.h文件中会有一个UIViewController的一个category,里面定义着一个UINavigationItem的变量。

三、生命周期
先说明一下控制器生命周期的几个方法

- (void)viewDidLoad {
    [super viewDidLoad];
    NSLog(@"view加载完成");
}
- (void)viewWillAppear:(BOOL)animated {
    NSLog(@"view即将出现");
}
- (void)viewDidAppear:(BOOL)animated {
    NSLog(@"view已经出现");
}
- (void)viewWillDisappear:(BOOL)animated {
    NSLog(@"one view即将消失");
}
-(void)viewDidDisappear:(BOOL)animated {
    NSLog(@"view已经消失");
}
- (void)dealloc {
    NSLog(@"view已经销毁");
}

导航控制器跳转场景
第一个控制器:OneViewControllers


OneViewControllers 代码

第二个控制器:TwoViewControllers


TwoViewControllers 代码

第三个控制器: ThreeViewControllers
ThreeViewControllers 代码

然后运行:

这里写图片描述

可以看出调用的方法是:viewDidLoad -> viewWillAppear -> viewDidAppear,这个很好理解,接下来:
然后点击跳转到第二个控制器button会怎样呢?
这里写图片描述

可以看出是这样的执行顺序:
oneView的viewWillDisappear -> twoView的viewDidLoad ->twoView的viewWillAppear -> oneView的ViewDidDisAppear ->twoView的ViewDidAppear
它是把第一个控制器先移走,然后装载并且显示第二个控制器,并没有把第一个控制器销毁,而是把它放到了一个内存中的一个位置,是一个弹栈的过程,将第一个控制器弹出。
那么如果点回第一个控制器会怎么样呢?
这里写图片描述

没错,第二个控制器被销毁啦,第一个控制器被压回了栈中,变成了栈顶。为什么要把第二个控制器销毁呢?其实很容易想出来,如果我们一直保留着下一层控制器,那么内存占用肯定会越来越多,但是第一层的控制器你肯定是要回来的,所以没有必要销毁。
那肯定会有人迷惑,如果从第三个控制器直接跳转到第一控制器,第二个控制器会怎样?其实,第二个控制器,也是会销毁的。试验一下:
这里写图片描述

可以看出,在oneView出现之前就把twoView给销毁啦
总结:① 当一个控制器向子控制器跳转时:先执行oneView的viewWillDisappear -> twoView的viewDidLoad ->twoView的viewWillAppear -> oneView的ViewDidDisAppear ->twoView的ViewDidAppear 第一个控制器并不会被销毁

② 当子控制器向上跳转时,期间的子控制器包括自己都会被销毁。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容