viewController详解

转自:http://hi.baidu.com/ericnew/item/49d81de66d1987f7e1a5d40ewindows

1、生命周期app

 

当一个视图控制器被建立,并在屏幕上显示的时候。 代码的执行顺序
一、 alloc                                   建立对象,分配空间
二、init (initWithNibName) 初始化对象,初始化数据
三、loadView                          从nib载入视图 ,一般这一步不须要去干涉。除非你没有使用xib文件建立视图
四、viewDidLoad                   载入完成,能够进行自定义数据以及动态建立其余控件
五、viewWillAppear              视图将出如今屏幕以前,立刻这个视图就会被展示在屏幕上了
六、viewDidAppear               视图已在屏幕上渲染完成函数

当一个视图被移除屏幕而且销毁的时候的执行顺序,这个顺序差很少和上面的相反
一、viewWillDisappear            视图将被从屏幕上移除以前执行
二、viewDidDisappear             视图已经被从屏幕上移除,用户看不到这个视图了
三、dealloc                                 视图被销毁,此处须要对你在init和viewDidLoad中建立的对象进行释放布局

关于viewDidUnload :在发生内存警告的时候若是本视图不是当前屏幕上正在显示的视图的话,  viewDidUnload将会被执行,本视图的全部子视图将被销毁,以释放内存,此时开发者须要手动对viewLoad、viewDidLoad中建立 的对象释放内存。 由于当这个视图再次显示在屏幕上的时候,viewLoad、viewDidLoad 再次被调用,以便再次构造视图。动画

 

 

2、view的加载过程ui

 

文字说明在表述流程的时候老是很费力的,我又找到了以下的两张图spa

 

 

跟随以下文字理解viewController对view加载过程:设计

1 先判断子类是否重写了loadView,若是有直接调用。以后调viewDidLoad完成View的加载。3d

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的加载。

 

3、view卸载过程图

 

 

跟随如下文字理解卸载过程:

1 系统发出警告或者ViewController自己调用致使didReceiveMemoryWarning被调用

2 调用viewWillUnload以后释放View

3 调用viewDidUnload

 

4、模拟器的调用顺序

我构架了这样一个环境,在该环境中有两个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,最后发现依然不存在,因此上述三个函数分别返回了失败,加载完成

但矛盾的地方是:为何上述三个函数自己没有执行到?底层到底作了什么?

 

5、view和ViewController的建立阶段,关于何时应该干什么

一、init

Allocating critical data structures required by your view controller

不要出现建立view的代码。良好的设计,在init里应该只有相关数据的初始化,并且这些数据都是比较关键的数据。init里不要掉self.view,不然会致使viewcontroller建立view。(由于view是lazyinit的)。

二、loadView

Creating your view objects

只初始化view,通常用于建立比较关键的view如tableViewController的 tabView,UINavigationController的navgationBar,不可掉用view的getter(在掉super  loadView前),最好也不要初始化一些非关键的view。若是你是从nib文件中建立的viewController在这里必定要首先调用 super的loadView方法,但建议不要重载这个方法。

三、viewDidLoad 

Allocating or loading data to be displayed in your view

这时候view已经有了,最适合建立一些附加的view和控件了。有一点须要注意的是,viewDidLoad会调用屡次(viewcontroller可能屡次载入view,参见图2)。

四、viewWillAppear 这个通常在view被添加到superview以前,切换动画以前调用。在这里能够进行一些显示前的处理。好比键盘弹出,一些特殊的过程动画(好比状态条和navigationbar颜色)。

五、viewDidAppear 通常用于显示后,在切换动画后,若是有须要的操做,能够在这里加入相关代码。

六、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时会从新建立。

七、dealloc

Releasing critical data structures required by your view controller

6、几点备注:

一、按结构能够对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会常常被继承,用来显示不一样的数据给用户。而第二种不多被继承,除非你真的须要自定义它。

 

二、当view被添加其余view中以前时,会调用viewWillAppear,而以后会调用viewDidAppear。

当view从其余view中移出以前时,会调用viewWillDisAppear,而以后会调用viewDidDisappear。

当view不在使用,并且是disappeared,受到内存警告时,那么viewController会将view释放并将其指向nil。

 

三、因为Controller加载View时,会自动将一些View对象指向其对应的IBOutlet变量。

因此当view被卸载时咱们必须在viewDidUnload将这些变量release掉,ViewController不会自动作这件事。

具体作法是将变量设置为空,(注意和dealloc中将变量release的区别)注意此时Controller的view属性是空的。

相关文章
相关标签/搜索