浅究iOS视图控制器的生命周期

 视图控制器的生命周期是指一个或多个视图控制器从创建到释放的整个过程。当视图控制器在不同状态之间转换时,系统会在适当的时候自动调用viewDidLoad、viewWillAppear:、viewWillDisappear:等一系列方法。当我们需要在生命周期的不同时期执行不同类型的方法时,通常会通过重写这些方法来执行相应的操作。在这里我们主要介绍这些与视图控制器生命周期相关的方法以及它们的执行顺序。
     一、视图控制器生命周期相关的方法
    ① awakeFromNib
    严格来说该方法不属于视图控制器生命周期的范围,但是在viewController的初始化中仍然有一定的作用。
  在视图加载之前发生,当对象(控制器或视图、按钮之类)从storyboard解档出来时调用,此时对象的所有的出口(outlets)和动作(actions)连接已经建立。
  可以在该方法中执行一些无法放到viewDidLoad或viewWillAppear:方法中执行的初始化操作。比如,可以自定义控件的默认配置以匹配用户首选项或其他控件中的值,也可以使用它将各个控件恢复到应用程序的某些先前状态。
     ② loadView
     在视图开始加载时调用。
     该方法主要用于创建控制器管理的视图,但是如果想对视图执行任何其他初始化操作,应该放在viewDidLoad方法中。
    该方法不会被直接调用,只有当视图控制器去请求相应的view属性,并且获取不到视图对象(self.view = nil)时,才会调用此方法进行加载或者创建对应的视图。
    通常情况下,视图在加载过程中,如果视图控制器具有关联的nib文件(控制器从storyboard实例化或者通过initWithNibName:bundle:方法指定了nib文件),该方法会直接从nib文件加载视图。如果视图控制器没有关联的nib文件,该方法会创建一个空白的UIView对象。
  如果使用IB创建视图、初始化视图控制器,一般不需要重写该方法,系统会默认调用该方法创建对象(这也就是为什么视图控制器创建好了之后就存在一个view的原因)。如果使用手动创建视图,则需要重写该方法,并将视图层级结构的根视图分配给控制器的view属性(self.view = theRootView)。需要注意的是,我们手动创建的视图应该是唯一的实例对象,不应与任何其他视图控制器对象共享,因此在重写loadView方法中不应该调用[super loadView]。
   ③ viewDidLoad
    在视图创建完成后、出现在屏幕之前调用,即视图控制器将其视图层次结构加载到内存后就会调用该方法,不管它是从nib文件加载的还是使用代码在loadView方法中加载的。
    在一个生命周期内只会被调用一次。
    可以使用该方法执行视图控制器相关的一次性初始化操作,但是不要在该方法中添加任何关于视图几何形状的初始化信息。这是因为当viewDidLoad被调用时,视图控制器还没有显示到界面中,视图的边界还没有确定下来,如果让它运行在一个不同的设备上,或者在不同的地方,或者被旋转之类,那么当它展示在屏幕上时,可能就不会出现在预定的位置。
    ④ viewWillAppear
    在视图出现在屏幕上之前调用,用于通知视图控制器将其视图即将添加到视图层次结构中。
    该方法表示视图将要出现,但是不保证视图将变得可见,视图也有可能被其他视图覆盖或隐藏等。
    可以使用该方法来执行视图显示在屏幕上之前所需的任何操作。例如用来更改状态栏的方向或样式等,以便与正在呈现的视图的方向或样式进行协调。
    可以在这里放置一些初始化的代码,比如需要执行某些基于数据的初始化操作,而这些数据可能会在视图控制器的视图离开屏幕时发生变化。也适合于对不可见时可能改变的内容进行同步,包括准备第一次出现前发生的变化等。但是不要在该方法中添加一次性初始化内容。因为当应用中有多个MVC时,它们会交替出现消失,导致该方法被多次调用,影响效率。
  也可以在该方法中添加一些用于实现优化的代码或者耗费资源的操作。例如在viewDidLoad中进行网络调用时,如果MVC始终没有出现在屏幕上,那么viewDidLoad中的网络调用就浪费了时间,此时如果将网络调用的代码放在viewWillAppear:中执行可能会更好一些。
    ⑤ viewDidAppear
    在视图出现在屏幕上之后被调用,用于通知视图控制器已经将其视图添加到应用程序的视图层次结构中了。
    该方法表示视图已经出现在屏幕上,但是并不保证视图是可见的,视图可能被其他视图覆盖或隐藏。
    可以使用该方法来执行视图显示在屏幕上之后所需的任何操作。比如获取数据或者显示动画等。
     ⑥ viewWillDisappear
     在视图离开屏幕之前调用,用于通知视图控制器其视图即将从应用程序的视图层次结构中删除。
    该方法表示视图即将从屏幕上离开,但是只有在实际删除视图之前才会调用。
    通常不会在该方法中执行太多内容,主要用来提交更改、撤销视图第一响应者的状态或其他相关的清除操作。例如,如果有动画之类的,可以在这里停止动画和记住当前状态,以希望控制器不再占用内存资源,当再次回到屏幕上时会再次调用到viewWillAppear:,可以再同步回去以便恢复。除此之外,还可以使用该方法逆向更改在viewDidAppear:方法中视图首次呈现的状态栏方向或样式。
     ⑦ viewDidDisappear
     在视图离开屏幕之后调用,用于通知视图控制器其视图已经从应用程序的视图层次结构中删除。
    该方法表示视图已经从屏幕上消失,但是只有在视图真正从视图层次结构中删除时才会调用。
    可以使用该方法执行关闭视图等相关操作。
    ⑧ viewWillLayoutSubviews
    在视图布局发生变化的时候调用,用于通知视图控制器它的视图即将布局其子视图。
   当视图发生变化时,常常会导致视图布局发生变化,此时视图会调整其子视图的位置。比如进行旋转设备等操作,会多次调用到该方法。
   重写该方法可以在视图显示其子视图之前进行更改。
   可以在这里添加几何相关的代码。
   ⑨ viewDidLayoutSubviews
   在视图布局发生变化的时候调用,用于通知视图控制器它的视图刚刚布局完其子视图。
   当视图控制器的视图边界发生变化时,视图调整其子视图的位置,然后系统调用该方法。但是由于每个子视图负责调整自己的布局,调用该方法并不表示子视图的各个布局已被调整。
    可以在这里执行布局相关的操作。例如,将手机从竖屏变为横屏,自动布局会尝试将所有元素移动至合适的位置,尽管并不总能实现,但它会尝试。在此之前,系统会调用viewWillLayoutSubviews,而在完成尝试之后才会调用到viewDidLayoutSubviews。由于自动布局的限制,有些元素可能没有清楚地表明要移动到哪里,此时可以重写该方法手动调整一些需要布局的元素,以便在视图显示其子视图后进行更改。
   ⑩ didReceiveMemoryWarning
   当应用程序收到内存警告时,会将该消息发送到视图控制器。但是应用程序不会直接调用该方法,只有当系统确定可用内存空间很低时才会调用。

通常在该方法中执行一些释放内存的操作。需要说明的是,内存不足并不代表你的应用占了很大的内存空间,也许只是手机上运行的所有应用一起占了很大的内存,需要释放一些空间,它可能向很多应用都发送了这个消息。对于是否生成这个警告,完全由系统决定。当收到警告后,唯一的责任就是试着释放内存,即堆中的内容,也就是将强指针设置为nil。在这里举一个处理内存警告的例子,比如要展示一幅图像或播放一段声音通常都需要很多内存,但是如果视图控制器正在屏幕上显示,就不能释放那张图像,即使收到了didReceiveMemoryWarning消息,其实也没有太多可做的,但是如果有一张可选图像之类的,并且现在不在屏幕上,只要可以重新创建它,我们就可以先将它设为nil,不管是从文件系统中重新创建还是网络调用重新下载一幅,只要图像不是立刻需要就可以。尤其是不在屏幕上时,也可以响应这个警告。
二、视图控制器生命周期的执行顺序(针对单个控制器)
① 视图控制器是从storyboard中创建的

1551364008812.jpg

② 视图控制器是纯代码创建的
浅究iOS视图控制器的生命周期_第1张图片
1551364290797.jpg

三、跳转界面(push/present各个控制器相应的方法调用顺序)
① 使用push跳转一个xib创建的视图控制器,不使用动画过渡
浅究iOS视图控制器的生命周期_第2张图片
BF7229F7-6FE5-4F9B-A6CF-413B1C4173F8.png

② 使用push跳转一个xib创建的视图控制器,使用动画过渡
浅究iOS视图控制器的生命周期_第3张图片
1C475B5B-B552-4D6D-9D81-F1816302C104.png

③ 点击back按钮返回上一个视图控制器
浅究iOS视图控制器的生命周期_第4张图片
A3A03FEE-9751-471A-9B09-6320EC117064.png

④使用present,进入一个纯代码创建的控制器,使用/使用动画过渡都一样
浅究iOS视图控制器的生命周期_第5张图片
732694F1-1489-458B-99ED-2FDA7085A49D.png

⑤ 点击dismiss按钮返回上一个视图控制器
浅究iOS视图控制器的生命周期_第6张图片
72ECB73A-65BF-4043-81BB-2765ACE2AB13.png

参考链接: https://github.com/darkjoin/Learning/wiki/%E8%A7%86%E5%9B%BE%E6%8E%A7%E5%88%B6%E5%99%A8%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F

你可能感兴趣的:(浅究iOS视图控制器的生命周期)