iOS 控制器生命周期

1,单个viewController的生命周期

①,initWithCoder:(NSCoder *)aDecoder:(如果使用storyboard或者xib)

②,loadView:加载view

③,viewDidLoad:view加载完毕

④,viewWillAppear:控制器的view将要显示

⑤,viewWillLayoutSubviews:控制器的view将要布局子控件

⑥,viewDidLayoutSubviews:控制器的view布局子控件完成

这期间系统可能会多次调用viewWillLayoutSubviews 、 viewDidLayoutSubviews 俩个方法

⑦,viewDidAppear:控制器的view完全显示

⑧,viewWillDisappear:控制器的view即将消失的时候

这期间系统也会调用viewWillLayoutSubviews 、viewDidLayoutSubviews 两个方法

⑨,viewDidDisappear:控制器的view完全消失的时候

⑩,didReceiveMemoryWarning(内存满时)

当程序发出一个内存警告--->

系统询问控制器有View吗--->如果有View

系统询问这个View能够销毁吗---->通过判断View是否在Windown上面,如果不在,就表示可以销毁

如果可以销毁,就执行viewWillUnLoad()----->对你的View进行一次release,此时View就为nil

然后调用viewDidUnLoad()----->一般还会在这个方法里将一些不需要属性清空

2,多个viewControllers跳转

当我们点击push的时候首先会加载下一个界面然后才会调用界面的消失方法

initWithCoder:(NSCoder *)aDecoder:ViewController2(如果用xib创建的情况下)

loadView:ViewController2

viewDidLoad:ViewController2

viewWillDisappear:ViewController1将要消失

viewWillAppear:ViewController2将要出现

viewWillLayoutSubviewsViewController2

viewDidLayoutSubviewsViewController2

viewWillLayoutSubviews:ViewController1

viewDidLayoutSubviews:ViewController1

viewDidDisappear:ViewController1完全消失

viewDidAppear:ViewController2完全出现

3,相关解释

①,loadView()

若控制器有关联的 Nib 文件,该方法会从 Nib 文件中加载 view;如果没有,则创建空白 UIView 对象。

自定义实现不应该再调用父类的该方法。

②,viewDidLoad()

view 被加载到内存后调用viewDidLoad()。

重写该方法需要首先调用父类该方法。

该方法中可以额外初始化控件,例如添加子控件,添加约束。

该方法被调用意味着控制器有可能(并非一定)在未来会显示。

在控制器生命周期中,该方法只会被调用一次。

③,viewWillAppear()

该方法在控制器 view 即将添加到视图层次时以及展示 view 时所有动画配置前被调用。

重写该方法需要首先调用父类该方法。

该方法中可以进行操作即将显示的 view,例如改变状态栏的取向,类型。

该方法被调用意味着控制器将一定会显示。

在控制器生命周期中,该方法可能会被多次调用。

注意:

如果A控制器present到B控制器,B控制器dismiss的时候,A的viewWillAppear不会被调用

④,viewWillLayoutSubviews()

该方法在通知控制器将要布局 view 的子控件时调用。

每当视图的 bounds 改变,view 将调整其子控件位置。

该方法可重写以在 view 布局子控件前做出改变。

该方法的默认实现为空。

该方法调用时,AutoLayout 未起作用。

在控制器生命周期中,该方法可能会被多次调用。

⑤,viewDidLayoutSubviews()

该方法在通知控制器已经布局 view 的子控件时调用。

该方法可重写以在 view 布局子控件后做出改变。

该方法的默认实现为空。

该方法调用时,AutoLayout 已经完成。

在控制器生命周期中,该方法可能会被多次调用。

⑥,viewDidAppear()

该方法在控制器 view 已经添加到视图层次时被调用。

重写该方法需要首先调用父类该方法。

该方法可重写以进行有关正在展示的视图操作。

在控制器生命周期中,该方法可能会被多次调用。

⑦,viewWillDisappear()

该方法在控制器 view 将要从视图层次移除时被调用。

类似 viewWillAppear()。

该方法可重写以提交变更,取消视图第一响应者状态。

⑧,viewDidDisappear()

该方法在控制器 view 已经从视图层次移除时被调用。

类似 viewDidAppear()

该方法可重写以清除或隐藏控件。

⑨,didReceiveMemoryWarning()

当内存预警时,该方法被调用。

不能直接手动调用该方法。

该方法可重写以释放资源、内存。

⑩,deinit

控制器销毁时(离开堆),调用该方法。

可以移除通知,调试循环测试

总结:

当屏幕旋转,view 的 bounds 改变,其内部的子控件也需要按照约束调整为新的位置,因此也调用了 viewWillLayoutSubviews() 和 viewDidLayoutSubviews()。

当在一个控制器内 Present 新的控制器,原先的控制器并不会销毁,但会消失,因此调用了viewWillDisappear和viewDidDisappear方法。

如果新的控制器 Dismiss,即清除自己,原先的控制器会再一次出现,因此调用了其中的viewWillAppear和viewDidAppear方法。

若 loadView() 没有加载 view,viewDidLoad() 会一直调用 loadView() 加载 view,因此构成了死循环,程序即卡死。原文

推荐阅读更多精彩内容