View和viewController的生命周期
View和viewController的生命周期
一、ViewController的职责
对内管理与之关联的View,对外跟其他ViewController通信和协调。对于与之关联的View,ViewController总是在需要的时候才加载视图,并在不需要的时候卸载视图,所以也同时担当了管理应用资源的责任
二、ViewController的生命周期
View是指Controller的View。它作为Controler的属性,生命周期在Controller的生命周期内。就是说你的Controller不能在view释放前就释放了。
viewController的生命周期图
需要说明的是:当你alloc并init了一个ViewController时,这个ViewController应该是还没有创建view的。ViewController的view是使用了lazyInit方式创建,就是说你调用的view属性的getter:[self view]。在getter里会先判断view是否创建,如果没有创建,那么会调用loadView来创建view。loadView完成时会继续调用viewDidLoad。loadView和viewDidLoad的一个区别就是:loadView时还没有view。而viewDidLoad时view以及创建好了。
三、view的加载过程
文字说明在表述流程的时候总是很费力的,我又找到了如下的两张图
view加载过程图
跟随如下文字理解viewController对view加载过程:
1 先判断子类是否重写了loadView,如果有直接调用。之后调viewDidLoad完成View的加载。
2 如果是外部通过调用initWithNibName:bundle指定nib文件名的话,ViewController记载此nib来创建View。
3 如果initWithNibName:bundle的name参数为nil,则ViewController会通过以下两个步骤找到与其关联的nib。
A 如果类名包含Controller,例如ViewController的类名是MyViewController,则查找是否存在MyView.nib;
B 找跟ViewController类名一样的文件,例如MyViewController,则查找是否存在MyViewController.nib。
4 如果子类没有重写的loadView,则ViewController会从StroyBoards中找或者调用其默认的loadView,默认的loadView返回一个空白的UIView对象。
注意第一步,ViewController是判断子类是否重写了loadView,而不是判断调用子类的loadView之后ViewController的View是否为空。就是说,如果子类重写了loadView的话,不管子类在loadView里面能否获取到View,ViewController都会直接调viewDidLoad完成View的加载。
view卸载过程图
跟随以下文字理解卸载过程:
1 系统发出警告或者ViewController本身调用导致didReceiveMemoryWarning被调用
2 调用viewWillUnload之后释放View
3 调用viewDidUnload
四、模拟器的调用顺序
我构架了这样一个环境,在该环境中有两个viewController,姑且命名为A和B,tag分别为1和2,A控制程序启动的时候即加载的界面,在A中放一个按钮,按下后会通过segue来调用到界面B;B 中页放一个按钮,通过执行
[self dismissModalViewControllerAnimated:YES];
来返回界面A
然后检测所有的函数调用,依次如下
加载A的时候依次调用
1 initWithCoder
1 loadView //如果说你进行了重写,会在这里调用,这一步可以参考下文
1 viewDidLoad
1 viewWillAppear
1 viewWillLayoutSubviews
1 viewDidLayoutSubviews
1 viewDidAppear
切换至B的时候依次调用
2 initWithCoder //先将2初始化
1 prepareForSegue //调用1的准备过度的函数,所以在该函数中可以对界面B的一些相关属性进行赋值
2 loadView //如果这里进行了重写
2 viewDidLoad //2界面加载
1 viewWillDisappear
2 viewWillAppear
2 viewWillLayoutSubviews
2 viewDidLayoutSubviews
2 viewDidAppear
1 viewDidDisappear
从B切换回A的时候依次调用
2 viewWillDisappear
1 viewWillAppear
1 viewDidAppear
2 viewDidDisappear
2 dealloc
顺序总结下来加载依次为:加载 - 显示 - 布局
完成顺序依次为:完成布局 - 完成显示 - 完成加载
小注:-(void)loadView;函数如果重写,下面是一个可能的demo
-(void)loadView
{
CGRect applicationFrame = [[UIScreenmainScreen] applicationFrame];
UIView *contentView = [[UIViewalloc] initWithFrame:applicationFrame];
contentView.backgroundColor = [UIColordarkGrayColor];
self.view = contentView;
UILabel *lab = [[UILabelalloc]initWithFrame:CGRectMake(100, 100, 100, 100)];
lab.text = @"HelloWorld";
[self.viewaddSubview:lab];
}
loadView虽然返回值为空,但必须在函数体内对self.view进行赋值,否则会在建立该界面的时候收到如下的log信息:
Application windows are expected to have a root view controller at the end of application launch
具体执行顺序为:代码执行了initWithCoder之后直接调用了三次loadView函数,并且没有调用其它函数(包括viewDidLoad 、viewWillDisappear、viewWillLayoutSubviews)
疑问:
暂不清楚为什么会调用三次,我的猜测是:上述三个函数分别检测了一遍view是否存在,发现不存在,所以各自调用了一遍viewLoad,最后发现依然不存在,所以上述三个函数分别返回了失败,加载完成
但矛盾的地方是:为什么上述三个函数本身没有执行到?底层到底做了什么?
五、view和ViewController的创建阶段,关于什么时候应该干什么
1、init
Allocating critical data structures required by your view controller
不要出现创建view的代码。良好的设计,在init里应该只有相关数据的初始化,而且这些数据都是比较关键的数据。init里不要掉self.view,否则会导致viewcontroller创建view。(因为view是lazyinit的)。
2、loadView
Creating your view objects
只初始化view,一般用于创建比较关键的view如tableViewController的tabView,UINavigationController的navgationBar,不可掉用view的getter(在掉super loadView前),最好也不要初始化一些非关键的view。如果你是从nib文件中创建的viewController在这里一定要首先调用super的loadView方法,但建议不要重载这个方法。
3、viewDidLoad
Allocating or loading data to be displayed in your view
这时候view已经有了,最适合创建一些附加的view和控件了。有一点需要注意的是,viewDidLoad会调用多次(viewcontroller可能多次载入view,参见图2)。
4、viewWillAppear 这个一般在view被添加到superview之前,切换动画之前调用。在这里可以进行一些显示前的处理。比如键盘弹出,一些特殊的过程动画(比如状态条和navigationbar颜色)。
5、viewDidAppear 一般用于显示后,在切换动画后,如果有需要的操作,可以在这里加入相关代码。
6、viewDidUnload
Releasing references to view objects
Releasing data that is not needed when your view is not displayed
这时候viewController的view已经是nil了。由于这一般发生在内存警告时,所以在这里你应该将那些不在显示的view释放了。比如你在viewcontroller的view上加了一个label,而且这个label是viewcontroller的属性,那么你要把这个属性设置成nil,以免占用不必要的内存,而这个label在viewDidLoad时会重新创建。
7、dealloc
Releasing critical data structures required by your view controller
六、几点备注:
1、按结构可以对iOS的所有ViewController分成两类:
1)、主要用于展示内容的ViewController,这种ViewController主要用于为用户展示内容,并与用户交互,如UITableViewController,UIViewController。
2)、用于控制和显示其他ViewController的ViewController。这种ViewController一般都是一个ViewController的容器。如UINavigationController,UITabbarController。它们都有一个属性:viewControllers。其中UINavigationController表示一种Stack式结构,push一个ViewController或pop一次,因此后一个ViewController一般会依赖前一个ViewController。而UITabbarController表示一个Array结构,各个ViewController是并列的。
第一种ViewController会经常被继承,用来显示不同的数据给用户。而第二种很少被继承,除非你真的需要自定义它。
2、当view被添加其他view中之前时,会调用viewWillAppear,而之后会调用viewDidAppear。
当view从其他view中移出之前时,会调用viewWillDisAppear,而之后会调用viewDidDisappear。
当view不在使用,而且是disappeared,受到内存警告时,那么viewController会将view释放并将其指向nil。
3、由于Controller加载View时,会自动将一些View对象指向其对应的IBOutlet变量。
所以当view被卸载时我们必须在viewDidUnload将这些变量release掉,ViewController不会自动做这件事。
具体做法是将变量设置为空,(注意和dealloc中将变量release的区别)注意此时Controller的view属性是空的。
事例
- (void)viewDidLoad
{
NSLog(@"加载之后");
[superviewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
-(void)viewDidAppear:(BOOL)animated
{
NSLog(@"动画qian");
}
-(void)viewDidDisappear:(BOOL)animated
{
NSLog(@"动画后");
}
- (void)viewDidUnload
{
NSLog(@"加载之后");
[superviewDidUnload];
// Release any retained subviews of the main view.
}
-(void)viewWillAppear:(BOOL)animated
{
NSLog(@"显示之前");
}
-(void)viewWillDisappear:(BOOL)animated
{
NSLog(@"显示之hou");
}
View和viewController的生命周期的更多相关文章
- iOS view和viewController的生命周期
一.ViewController的职责 对内管理与之关联的View,对外跟其他ViewController通信和协调.对于与之关联的View,ViewController总是在需要的时候才加载视图,并 ...
- ViewController的生命周期分析和使用
iOS的SDK中提供很多原生ViewController,大大提高了我们的开发效率,下面是我的一些经验. 一.结构 按结构可以对iOS的所有ViewController分成两类:1.主要用于展示内容的 ...
- ViewController的生命周期
# ViewController 的生命周期 # ViewController的生命周期中各个方法的流程如下: init loadView :加载view viewDidLoad :view加载完毕 ...
- Unity 3D Framework Designing(3)——构建View和ViewModel的生命周期
> 对于一个View而言,本质上是一个MonoBehaviour.它本身就具备生命周期这个概念,比如,Awake,Start,Update,OnDestory等.这些是非常好的方法,可以让开发者 ...
- Unity应用架构设计(3)——构建View和ViewModel的生命周期
对于一个View而言,本质上是一个MonoBehaviour.它本身就具备生命周期这个概念,比如,Awake,Start,Update,OnDestory等.这些是非常好的方法,可以让开发者在各个阶段 ...
- iOS viewController 和 view 的创建消失生命周期总结
控制器创建的生命周期 1. 如果从stroryBoard 中产生一个controller,那么会先调用initWithCoder:, awakeFromNib, loadView,viewDidLoa ...
- iOS - ViewController的生命周期
iOS SDK中提供很多原生的ViewController,大大提高了我们的开发效率:那么下面我们就根据开发中我们常用的ViewController谈一谈它的生命周期: (一)按照结构和用法可以对iO ...
- [zhang] ViewController的生命周期分析和使用
iOS的SDK中提供很多原生ViewController,大大提高了我们的开发效率,下面是我的一些经验. 一.结构 按结构可以对iOS的所有ViewController分成两类:1.主要用于展示内容的 ...
- ios ViewController的生命周期分析和基本使用逻辑
按结构可以对iOS的所有ViewController分成两类:1.主要用于展示内容的ViewController,这种ViewController主要用于为用户展示内容,并与用户交互,如UITable ...
随机推荐
- 【类似N^N做法的斐波那契数列】【HDU1568】 Fibonacci
Fibonacci Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total ...
- tomcat-maven-plugin 插件使用
配置 在pom.xm 加入以下xml. <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId&g ...
- JS中表格的全选和删除要注意的问题
在项目开发中,由于刚刚开始做项目,我对js还不是很精通,所以在用js对表格的全选和删除中遇到了不少问题,后来通过查找资料解决了,之后总结了一下关于js表格的全选和删除出现的一些问题,希望能帮助到大家. ...
- 对获取config文件的appSettings节点简单封装
转:http://www.cnblogs.com/marvin/archive/2011/07/29/EfficiencyAppSetting.html C#的开发中,无论你是winform开发还是w ...
- JSP 基础之 JSTL <c:forEach>用法
在JSP的开发中,迭代是经常要使用到的操作.例如,逐行的显示查询的结果等.在早期的JSP中,通常使用Scriptlets来实现Iterator或者Enumeration对象的迭代输出.现在,通过JST ...
- HDU 2072(单词数)题解
以防万一,题目原文和链接均附在文末.那么先是题目分析: [一句话题意] “就是统计一篇文章里不同单词的总数”(已经是一句话了..) [题目分析] 明显需要去重,上set,因为按行分析,又没有EOLN用 ...
- linux学习笔记之文件结构和函数
本文参考<UNIX环境高级编程> 一.基础介绍. 1:文件的构成. 1,首先声明,这里的文件和目录,表示普通的文件和目录.不确定是否可以应用到:设备,管道等特殊形式的文件(UNIX把它们也 ...
- mysql 时间戳按指定格式(Y-m-d)取出
之前做采集脚本,把采集的时间按unix时间戳的形式取出 那么在写sql语句的时候,需要按时间查询相应的记录,页面传进来的$time 是'2014-01'之类的字符串,那么怎么写sql呢 $sql ...
- 引用JS表单验证大全 以后方便查看用
1:js 字符串长度限制.判断字符长度 .js限制输入.限制不能输入.textarea 长度限制 2.:js判断汉字.判断是否汉字 .只能输入汉字 3:js判断是否输入英文.只能输入英文 4:js只能 ...
- Train Problem I
问题陈述: 杭州电子科技大学HANGZHOU DIANZI UNIVERSITY Online Judge Problem - 1022 问题解析: 栈(stack)的简单应用 代码详解: #incl ...