一、 大体流程:
(loadView/nib)文件来加view到内存-->viewDidLoad函数进一步初始化这些view-->内存不足时, 调用viewDidUnload函数释放views-->当需要使用view时又回到第一步。
loadView:
永远不要主导调用这个函数。
viewController 会在view的property被请求并且当前view值为nil时调用这个函数。如果你手动创建view, 你应该重载这个函数,切不要在重载的时候调用[super loadView]。viewDidLoad:
这个函数的作用主要是让你可以进一步的初始化你的views。
viewDidLoad通常负责的是view及其子view被加载进内存之后的数据初始化的工作,即视图的数据部分的初始化。viewDidUnLoad:
这个函数时viewDidLoad的对立函数。在程序内存欠缺时,这个函数被controller调用,来释放他的view以及view相关的对象。由于controller通常保存着view以及相关的object的引用,所以你必须使用这个函数来放弃这些对象的所有权以便内存回收,但不要释放那些难以重建的数据。viewWillAppear:
视图即将可见时调用,默认情况下不执行任何操作。viewDidAppear:
视图已完全过渡到屏幕上时调用。viewWillDisappear:
视图被驳回时调用,覆盖或以其他方式隐藏,默认情况下不执行任何操作。viewDidDisappear:
视图被驳回后调用,覆盖或以其他方式隐藏。默认情况下不执行任何操作。didReceiveMemoryWarning:
当程序内存过度时,系统会调用该方法。
二、Controller和View的生命周期
这里指的View是指Controller的View。它作为Controler的属性,生命周期在Controller的生命周期内。就是说你的Controller不能在view释放前就释放了。
当你alloc并iit了一个ViewController时,这个ViewController应该是还没有创建view的。ViewController的view是使用了lazyInit方式创建,就是说你调用的view属性的getter:[self view]。在getter里会先判断view是否创建,如果没有创建,那么会调用loadView来创建view。loadView完成时会继续调用viewDidLoad。loadView和viewDidLoad的一个区别就是:loadView时还没有view。而viewDidLoad时view以及创建好了。
当view被添加其他view中之前时,会调用viewWillAppear,而之后会调用viewDidAppear。
当view从其他view中移出之前时,会调用viewWillDisAppear,而之后会调用viewDidDisappear。
当view不在使用,而且是disappeared,受到内存警告时,那么viewController会将view释放并将其指向nil。
三、代码组织(如何设计良好的ViewController)
ViewController生命周期中有那么多函数,一个重要问题就是什么代码该写在什么地方。
- init里不要出现创建view的代码。良好的设计,在init里应该只有相关数据的初始化,而且这些数据都是比较关键的数据。init里不要掉self.view,否则会导致viewcontroller创建view。(因为view是lazyinit的)。
- loadView中只初始化view,一般用于创建比较关键的view如tableViewController的tabView,UINavigationController的navgationBar,不可掉用view的getter(在掉super loadView前),最好也不要初始化一些非关键的view。如果你是从nib文件中创建的viewController在这里一定要首先调用super的loadView方法,但建议不要重载这个方法。
- viewDidLoad 这时候view已经有了,最适合创建一些附加的view和控件了。
- viewWillAppear 这个一般在view被添加到superview之前,切换动画之前调用。在这里可以进行一些显示前的处理。比如键盘弹出,一些特殊的过程动画(比如状态条和navigationbar颜色)。
- viewDidAppear 一般用于显示后,在切换动画后,如果有需要的操作,可以在这里加入相关代码。
- viewDidUnload 这时候viewController的view已经是nil了。由于这一般发生在内存警告时,所以在这里你应该将那些不在显示的view释放了。比如你在viewcontroller的view上加了一个label,而且这个label是viewcontroller的属性,那么你要把这个属性设置成nil,以免占用不必要的内存,而这个label在viewDidLoad时会重新创建。
- 接下来看看ViewController中的view是如何被卸载的:
当系统发出内存警告时,会调用didReceiveMemoeryWarning方法,如果当前有能被释放的view,系统会调用viewWillUnload方法来释放view,完成后调用viewDidUnload方法,至此,view就被卸载了。此时原本指向view的变量要被置为nil,具体操作是在viewDidUnload方法中调用self.myButton = nil;
小结
小结一下:loadView和viewDidLoad的区别就是,loadView时view还没有生成,viewDidLoad时,view已经生成了,loadView只会被调用一次,而viewDidLoad可能会被调用多次(View可能会被多次加载),当view被添加到其他view中之前,会调用viewWillAppear,之后会调用viewDidAppear。当view从其他view中移除之前,调用viewWillDisAppear,移除之后会调用viewDidDisappear。当view不再使用时,受到内存警告时,ViewController会将view释放并将其指向为nil。
重要的事情在最后
ViewController的生命周期中各方法执行流程如下:init—>loadView—>viewDidLoad—>viewWillApper—>viewDidApper—>viewWillDisapper—>viewDidDisapper—>viewWillUnload->viewDidUnload—>dealloc