探究 UIViewController 生命周期
由于种种原因,掘金等第三方平台博客不再保证能够同步更新,欢迎移步 GitHub:github.com/kingcos/Per…。谢谢!
Lifecycle of UIViewController in iOS
Date | Notes | Swift | Xcode |
---|---|---|---|
2017-03-10 | 首次提交 | 3.0 | 8.2.1 |
前言
对象的生命周期一直是开发者所需要关心的,教授 CS193p 的老师 Paul 也详细的讲述了 UIViewController 的生命周期。为了记述这一过程,故作此文。由于 Xcode 提供了纯代码和 Storyboard(Xib 同理)两种布局 UI 的方式,因此初始化部分略有不同。
为了方便观察,我创建了一个 BaseViewController,继承自原本的 UIViewController,重写其中的生命周期方法,并让后续新的控制器继承自该控制器,以便观察。
本文对应的 Demo 可以在 github.com/kingcos/UIV… 查看、下载。
Initialization
Storyboard
OUTPUT: init(coder:) awakeFromNib()
init(coder:)
- 当使用 Storyboard 时,控制器的构造器为
init(coder:)
。 - 该构造器为必需构造器,如果重写其他构造器,则必须重写该构造器。
- 该构造器为可失败构造器,即有可能构造失败,返回 nil。
- 该方法来源自 NSCoding 协议,而 UIViewController 遵从这一协议。
- 该方法被调用意味着控制器有可能(并非一定)在未来会显示。
- 在控制器生命周期中,该方法只会被调用一次。
awakeFromNib()
- 当使用 Storyboard 时,该方法会被调用。
- 当调用该方法时,将保证所有的 outlet 和 action 连接已经完成。
- 该方法内部必须调用父类该方法,虽然默认实现为空,但 UIKit 中许多类的该方法为非空。
- 由于控制器中对象的初始化顺序不能确定,所以构造器中不应该向其他对象发送消息,而应当在
awakeFromNib()
中安全地发送。 - 通常使用
awakeFromNib()
可以进行在设计时无法完成的必要额外设置。
Code
OUTPUT: init(nibName:bundle:) - NibName: nil, Bundle: nil
init(nibName:bundle:)
- 当使用纯代码创建控制器,控制器的构造器为
init(nibName:bundle:)
。 - 虽然使用代码创建时调用了该构造器,但传入的参数均为 nil。
OUTPUT: loadView() viewDidLoad() viewWillAppear viewWillLayoutSubviews() - Optional((162.0, 308.0, 50.0, 50.0)) viewDidLayoutSubviews() - Optional((67.0, 269.0, 241.0, 129.0)) viewDidAppear viewWillDisappear viewDidDisappear deinit
loadView()
loadView()
即加载控制器管理的 view。- 不能直接手动调用该方法;当 view 被请求却为 nil 时,该方法加载并创建 view。
- 若控制器有关联的 Nib 文件,该方法会从 Nib 文件中加载 view;如果没有,则创建空白 UIView 对象。
- 如果使用 Interface Builder 创建 view,则务必不要重写该方法。
- 可以使用该方法手动创建视图,且需要将根视图分配为 view;自定义实现不应该再调用父类的该方法。
- 执行其他初始化操作,建议放在
viewDidLoad()
中。
viewDidLoad()
- view 被加载到内存后调用
viewDidLoad()
。 - 重写该方法需要首先调用父类该方法。
- 该方法中可以额外初始化控件,例如添加子控件,添加约束。
- 该方法被调用意味着控制器有可能(并非一定)在未来会显示。
- 在控制器生命周期中,该方法只会被调用一次。
viewWillAppear(_:)
- 该方法在控制器 view 即将添加到视图层次时以及展示 view 时所有动画配置前被调用。
- 重写该方法需要首先调用父类该方法。
- 该方法中可以进行操作即将显示的 view,例如改变状态栏的取向,类型。
- 该方法被调用意味着控制器将一定会显示。
- 在控制器生命周期中,该方法可能会被多次调用。
注意: 如果控制器 A 被展示在另一个控制器 B 的 popover 中,那么控制器 B 不会调用该方法,直到控制器 A 清除。
viewWillLayoutSubviews()
- 该方法在通知控制器将要布局 view 的子控件时调用。
- 每当视图的 bounds 改变,view 将调整其子控件位置。
- 该方法可重写以在 view 布局子控件前做出改变。
- 该方法的默认实现为空。
- 该方法调用时,AutoLayout 未起作用。
- 在控制器生命周期中,该方法可能会被多次调用。
viewDidLayoutSubviews()
- 该方法在通知控制器已经布局 view 的子控件时调用。
- 该方法可重写以在 view 布局子控件后做出改变。
- 该方法的默认实现为空。
- 该方法调用时,AutoLayout 已经完成。
- 在控制器生命周期中,该方法可能会被多次调用。
viewDidAppear(_:)
- 该方法在控制器 view 已经添加到视图层次时被调用。
- 重写该方法需要首先调用父类该方法。
- 该方法可重写以进行有关正在展示的视图操作。
- 在控制器生命周期中,该方法可能会被多次调用。
viewWillDisappear(_:)
- 该方法在控制器 view 将要从视图层次移除时被调用。
- 类似
viewWillAppear(_:)
。 - 该方法可重写以提交变更,取消视图第一响应者状态。
viewDidDisappear(_:)
- 该方法在控制器 view 已经从视图层次移除时被调用。
- 类似
viewDidAppear(_:)
。 - 该方法可重写以清除或隐藏控件。
didReceiveMemoryWarning()
- 当内存预警时,该方法被调用。
- 不能直接手动调用该方法。
- 该方法可重写以释放资源、内存。
deinit
- 控制器销毁时(离开堆),调用该方法。
Note
Rotation
OUTPUT: willTransition(to:with:) viewWillLayoutSubviews() - Optional((67.5, 269.5, 240.0, 128.0)) viewDidLayoutSubviews() - Optional((213.5, 123.5, 240.0, 128.0)) viewWillLayoutSubviews() - Optional((213.5, 123.5, 240.0, 128.0)) viewDidLayoutSubviews() - Optional((213.5, 123.5, 240.0, 128.0)) viewWillLayoutSubviews() - Optional((213.5, 123.5, 240.0, 128.0)) viewDidLayoutSubviews() - Optional((213.5, 123.5, 240.0, 128.0))
- 当 view 转变,会调用
willTransition(to:with:)
方法。 - 当屏幕旋转,view 的 bounds 改变,其内部的子控件也需要按照约束调整为新的位置,因此也调用了
viewWillLayoutSubviews()
和viewDidLayoutSubviews()
。
Present & Dismiss
OUTPUT: viewWillDisappear viewDidDisappear viewDidDisappear viewWillAppear viewDidAppear
- 当在一个控制器内 Present 新的控制器,原先的控制器并不会销毁,但会消失,因此调用了
viewWillDisappear
和viewDidDisappear
方法。 - 如果新的控制器 Dismiss,即清除自己,原先的控制器会再一次出现,因此调用了其中的
viewWillAppear
和viewDidAppear
方法。
死循环
class LoopViewController: UIViewController {override func loadView() {print(#function)}override func viewDidLoad() {print(#function)let _ = view}}
复制代码
OUTPUT: loadView() viewDidLoad() loadView() viewDidLoad() loadView() viewDidLoad() loadView() viewDidLoad() loadView()
- 若
loadView()
没有加载 view,viewDidLoad()
会一直调用loadView()
加载 view,因此构成了死循环,程序即卡死。
Reference
- CS193P_2017
- UIViewController 相关生命周期总结
也欢迎您关注我的微博 @萌面大道V & 简书
探究 UIViewController 生命周期相关推荐
- iOS对UIViewController生命周期和属性方法的解析
iOS对UIViewController生命周期和属性方法的解析 一.引言 作为MVC设计模式中的C,Controller一直扮演着项目开发中最重要的角色,它是视图和数据的桥梁,通过它的管理,将数据有 ...
- UIViewController 生命周期
前言 UIViewController 往往是 iOS 页面开发的基础,用户交互和数据展示都是由它来控制,了解了它的生命周期,就能做到:在合适的时机,做合适的事情. 顺序 下面对 UIViewCont ...
- Android零基础入门第86节:探究Fragment生命周期
2019独角兽企业重金招聘Python工程师标准>>> 一个Activity可以同时组合多个Fragment,一个Fragment也可被多个Activity 复用.Fragment可 ...
- UIViewController生命周期
2019独角兽企业重金招聘Python工程师标准>>> 转载于:https://my.oschina.net/notting/blog/77970
- UIViewController生命周期的理解
if (self = [super init])=======>if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOr ...
- 【iOS开发】-UIViewController加载过程和生命周期
文章目录 前言 ViewController执行过程的探讨 ViewControllerOne 函数介绍 顺序引入 ViewControllerSecond引入 ViewControllerOne点击 ...
- iOS UIViewController和UIView的生命周期
文章目录 UIViewController的生命周期 UIView的生命周期 UIViewController和UIView进入展示时整体生命周期调用顺序 开发技巧总结 UIViewControlle ...
- 关于FragmentManager动态管理Fragment时Fragment生命周期的探究
Fragment是Android中的重要组件,在Android 3.0的时候添加进来. 关于Fragment的生命周期,我相信了解过的开发人员都应该把以下方法脱口而出:onAttach, onCrea ...
- vue生命周期探究(一)
前言 在使用vue开发的过程中,我们经常会接触到生命周期的问题.那么你知道,一个标准的工程项目中,会有多少个生命周期勾子吗?让我们来一起来盘点一下: 根组件实例:8个 (beforeCreate.cr ...
最新文章
- 10.27 noip模拟试题
- [wordpress]更新插件时,免去FTP操作
- Android 系统(56)---深入浅析Android坐标系统
- 如何选择RabbitMQ和Kafka
- python自动化测试难不难_我从功能测试进阶到自动化测试工程师的经验总结~|Atstudy...
- 【Tricks】半监督深度学习训练和实现小Tricks
- selenium窗口截图操作
- 游戏开发中的向量数学
- 复盘:windows ubuntu 双系统引导恢复、分区表恢复
- 2018美团实习生招聘——K的倍数
- NET::ERR_INCOMPLETE_CHUNKED_ENCODING 200 (OK)
- 帮助台湾?匿名者组织攻击联合国和世界卫生组织网站
- Nginx反向代理的配置
- Neo4j 启动报错 Server shutdown initiated by request
- 华为云沙箱实验室的相关操作介绍
- 苹果服务器怎样推送消息,ios消息推送
- 网络安全培训试题及答案
- 医疗影像容积重建-物体坐标系和渲染图像坐标系
- JAVA的四种引用类型的作用——强引用、软引用、弱引用、虚引用
- linux下离线安装k8s集群1.19.4附带nfs存储(kubeadm方式)
热门文章
- 书山有径——走进清华大学图书馆
- wamp 安装monggo扩展
- python获取代码行号
- java回调机制及其实现(转)
- 与众不同 windows phone (32) - Communication(通信)之任意源组播 ASM(Any Source Multicast)...
- MSM--Memcached_Session_Manager介绍及使用
- Python学习入门基础教程(learning Python)--3.3.1 Python下的布尔表达式
- Windows下如何使用FTP命令
- css3 box-sizing属性
- Android中动态更新ListView