一、 大体流程:
-
(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:
视图即将可见时调用,默认情况下不执行任何操作。 -
viewWillLayoutSubViews:
视图在显示之前会布局子控件(将要布局子控件的时候调用) -
viewDidLayoutSubViews:
已经布局完子控件的时候调用 -
viewDidAppear:
视图已完全过渡到屏幕上时调用 -
viewWillDisappear:
视图被驳回时调用,覆盖或以其他方式隐藏,默认情况下不执行任何操作 -
viewDidDisappear:
视图被驳回后调用,覆盖或以其他方式隐藏。默认情况下不执行任何操作 -
didReceiveMemoryWarning:
当程序内存过度时,系统会调用该方法
二、Controller和View的生命周期
- 这里指的View是指Controller的View。它作为Controler的属性,生命周期在Controller的生命周期内。就是说你的Controller不能在view释放前就释放了。
- 当你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中之前时,会调用viewWillAppear,而view在显示之前会先调用viewWillLayoutSubViews以及viewDidLayoutSubViews来布局子控件,而之后才会调用viewDidAppear。
- 当view从其他view中移出之前时,会调用viewWillDisAppear,而之后会调用viewDidDisappear。
- 当view不在使用,而且是disappeared,受到内存警告时,那么viewController会将view释放并将其指向nil。
加载View的流程
1.先去判断当前控制器是不是从StoryBoard当中加载的,如果是,那么它就会从StoryBoard当中加载控制器的View.
2.如果不是从StoryBoard当中加载的, 那么它还会判断是不是从Xib当中创建的控制器.如果是,那么它就会从xib加载控制器的View.
* 加载Xib的时候会先看看有没有和控制器同名的Xib,有的话就加载;
* 如果没有的话就会查找下有没有控制器的名称去掉controller的xib,有的话就去加载.
3.如果也不是从Xib加载的控制器.那么它就会创建一个空的UIView.设为当前控制器的View.
三、代码组织(如何设计良好的viewController)
ViewController生命周期中有那么多函数,一个重要问题就是什么代码该写在什么地方。
- 1、
init
里不要出现创建view的代码。良好的设计,在init里应该只有相关数据的初始化,而且这些数据都是比较关键的数据。init里不要掉self.view,否则会导致viewcontroller创建view。(因为view是lazyinit的)。 - 2、
loadView
中只初始化view,一般用于创建比较关键的view如tableViewController的tabView,UINavigationController的navgationBar,不可掉用view的getter(在掉super loadView前),最好也不要初始化一些非关键的view。如果你是从nib文件中创建的viewController在这里一定要首先调用super的loadView方法,但建议不要重载这个方法。 - 3、
viewDidLoad
这时候view已经有了,最适合创建一些附加的view和控件了。 - 4、
viewWillAppear
这个一般在view被添加到superview之前,切换动画之前调用。在这里可以进行一些显示前的处理。比如键盘弹出,一些特殊的过程动画(比如状态条和navigationbar颜色)。 - 5、
viewWillLayoutSubViews
一般用于显示前,对子控件进行布局 - 6、
viewWillLayoutSubViews
子控件布局完成,可以在这方法里面对子控件进行一些初始化操作. - 7、
viewDidAppear
一般用于显示后,在切换动画后,如果有需要的操作,可以在这里加入相关代码。 - 8、
viewDidUnload
这时候viewController的view已经是nil了。由于这一般发生在内存警告时,所以在这里你应该将那些不在显示的view释放了。比如你在viewcontroller的view上加了一个label,而且这个label是viewcontroller的属性,那么你要把这个属性设置成nil,以免占用不必要的内存,而这个label在viewDidLoad时会重新创建。 - 9、接下来看看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—>viewWillAppear—>viewWillLayoutSubViews—>viewDidLayoutSubViews—>viewDidAppear—>viewWillDisappear—>viewDidDisappear—>viewWillUnload->viewDidUnload—>dealloc
网友评论