视图控制器对象的生命周期 (FWD)

视图控制器UIViewController是我们程序中视图和模型数据的纽带,是MVC设计模式中的控制层,我们视图的创建和数据的交互都是在UIViewController类或者其子类中进行的,我们何时何地去创建视图和进行数据交互都跟它的生命周期息息相关。
 
当我们创建一个视图控制器的时候,它的生命周期会涉及init、initWithNibName:bundle:、loadView、viewDidLoad、viewWillAppear、viewDidAppear、viewWillDisappear、viewDidDisappear、
didReceiveMemoryWarning、viewWillUnload、viewDidUnload这几个方法。
 
在他们当中有存在一个关键的角色就是视图控制器自身view视图,所以如果能很清楚的了解视图控制器view视图的加载过程,就能够明白视图控制器的生命周期,所以这篇文章就围绕这个view来理解视图控制器的生命周期。
 
init和initWithNibName:bundle:方法:
我们可以通过两种方式来实例化一个UIViewController,一个是init,另一个是initWithNibName:bundle:,如果我们通过init方法去实例化,执行init之后又会接着执行initWithNibName:bundle:方法去寻找有没有可用的NIB文件,如果有就可以直接使用NIB文件的视图控制器view视图,如果没有系统会调用loadView方法。在这个方法里,我们可以初始化一些数据,但不要引用视图控制器的view视图,因为这个时候view视图还没有创建。
 
loadView方法:
当程序进入到loadView方法中的时候,要做一个判断,是自定义一个view视图,还是不自定义,如果需要自己定义视图,就可以实例化一个UIView传递给视图控制器的view,如果不自定义,程序就会寻找有没有Storyboard文件,如果有就使用,如果没有系统会自动帮你创建一个空的视图,这里要注意一下,如果需要系统帮你创建,就需要调用[super  loadview],到现在我们虽然得到了视图控制器的view,但是这个时候它是没有放入内存的,只有这个方法执行完毕,程序会紧接着执行viewDidLoad,在执行viewDidLoadde 时候视图控制器的view才被真正的创建。
 
viewDidLoad方法:
这个时候如果我们通过NIB、Storyboard、自定义、系统自动创建中任何一个方法创建视图控制器的view视图后,就可以接着执行viewDidLoad其他代码,如果都没有,如果去引用视图控制器的view时,程序又会返回到loadView中去寻找这个view视图,而我们的loadView中也没有去创建,这时就会在loadView和viewDidLoad之间无限交替调用,我们的程序就会出错。如果这个view在之前创建了,这个时候就可以调用视图控制器的view视图的getter方法,并且可以往它里面添加子视图了,这就是为什么一般添加子视图的时候要在viewDidLoad方法里进行了。
 
 
viewWillAppear方法:
这个方法是当我们的视图控制器即将显示的时候调用,这个时候我们可以恢复一些用户数据,因为内存警告时,如果这个视图控制器没有在当前窗口显示,它的View就会被清除掉,下面会详细说,所以当再次显示的时候,我们需要恢复用户的数据。
 
viewDidAppear方法:
这个方法是视图控制器已经加载进来的时候调用。
 
viewWillDisappear方法:
这个方法是视图控制器将要消失的时候调用,这个时候我们可以保存当前的用户数据。
 
viewDidDisappear方法:
这个方法是视图控制器已经消失的时候调用。
 
下面说一说视图控制器的卸载:
 
didReceiveMemoryWarning、viewWillUnload、viewDidUnload方法:
 
当我们系统发出内存警告时会卸载没有显示在当前窗口的视图控制器的View视图,注意这里只是卸载view视图,而不会卸载视图控制器。
 
在ios6.0之前系统会调用didReceiveMemoryWarning这个方法,然后去找已经创建的试图控制器有没有加载view视图,如果已经加载,则会判断这个view视图是不是在当前窗口,如果不在当前窗口,就会先调用viewWillUnload方法告诉你这个视图控制器的视图即将被卸载掉,但是还没有变成nil,这个时候你也可以保存用户数据,防止数据丢失。这个方法执行完成之后会接着调用viewWillUnload方法,调用这个方法的时候不可见的视图控制器的view视图就release掉变成nil,这个时候需要你手动的把你加载到这个view中的子视图清空,设为nil。这个时候不显示的试图控制器的view视图就成功卸载了,那当我在将这个视图控制器的view再显示在window上时会不会就什么都没有了呢?不会,应为当你将这个视图显示出来的时候系统会重新加载一次,那是如何加载的呢?因为当你显示这个视图的时候会调用这个view,如果系统找不到这个view就会又一次执行loadView方法,然后再执行viewDidload,视图及其子视图就会再一次加载进来。
 
ios6.0之后就没有了viewWillUnload、viewDidUnload这两个方法,而是让我们自己判断视图是否在当前窗口,然后自己进行释放,而且试图控制器的view视图也是要自己去释放,系统不会自动为你释放,因此如果内存警告之后,你没有去释放,你的程序就可能闪退,然后崩溃掉。
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s