美文网首页
iOS 控制器生命周期

iOS 控制器生命周期

作者: 一代枭雄 | 来源:发表于2021-10-13 17:09 被阅读0次

    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,例如改变状态栏的取向,类型。

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

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

    注意:******

    ViewControllerA present一个ViewControllerB,如果是iOS13 默认UIModalPresentationAutomatic样式,当ViewControllerB dismiss 到 ViewControllerA的时候,不调用ViewControllerA里面的,viewWillAppear方法和viewDidAppear方法。

    modalPresentationStyle设置成UIModalPresentationFullScreen的模式,会调用viewWillAppear方法和viewDidAppear方法。

    ④,viewWillLayoutSubviews()

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

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

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

    该方法的默认实现为空。

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

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

    ⑤,viewDidLayoutSubviews()

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

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

    该方法的默认实现为空。

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

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

    ⑥,viewDidAppear()

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

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

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

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

    ⑦,viewWillDisappear()

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

    类似 viewWillAppear()。

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

    ⑧,viewDidDisappear()

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

    类似 viewDidAppear()

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

    ⑨,didReceiveMemoryWarning()

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

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

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

    ⑩,deinit

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

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

    总结:

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

    ViewControllerA present一个ViewControllerB,如果是iOS13 默认UIModalPresentationAutomatic样式,当ViewControllerB dismiss 到 ViewControllerA的时候,不调用ViewControllerA里面的,viewWillAppear方法和viewDidAppear方法。

    modalPresentationStyle设置成UIModalPresentationFullScreen的模式,会调用viewWillAppear方法和viewDidAppear方法。

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

    上面说的有些混乱了,下边看一下转场A viewwilldisappear,AviewDidDisappear和 B viewwillappear和viewdidappear的各种情况的出现顺序:

    Push: A-willDisappear-->B-willAppear-->A-didDisappear-->B-didAppear

    fullScreenPresent: A-willDisappear-->B-willAppear-->B-didAppear-->A-didDisappear

    OtherPresent: B-willAppear-->B-didAppear(因为A没有消失)

    TabBar: B-willAppear-->A-willDisappear-->A-didDisappear-->B-didAppear

    在每一种转场下,appear 与 disappear 都有一些不一样的顺序,一定要分清楚,不能一概而论。

    以下第一个出现的都是will,第二个都是did,will永远在did之前,因为一个是将要,一个是已经

    push:abab(最正常)

    fullScreenPresent:abba

    otherPresent:bb(a不消失,所以不调用)

    tabbar:baab

    附加面试题:load和initialize的区别

    ******:load是只要类所在的文件被引用就会被调用,而initialize是在类或者其子类的第一个方法被调用前调用。所以如果类没有被引用进项目,就不会调用load方法,即使类文件被引用进来,如果没有使用,那么initialize不会被调用。

    调用方式

    1、load是根据函数地址直接调用

    2、initialize是通过objc_msgSend调用

    调用时刻

    1、load是runtime加载类、分类的时候调用(只会调用一次)

    2、initialize是类第一次接收到消息的时候调用, 每一个类只会initialize一次(如果子类没有实现initialize方法, 会调用父类的initialize方法, 所以父类的initialize方法可能会调用多次)

    load和initializee的调用顺序

    1、load:

    先调用类的load, 在调用分类的load

    先编译的类, 优先调用load, 调用子类的load之前, 会先调用父类的load

    先编译的分类, 优先调用load

    2、initialize

    先初始化分类, 后初始化子类

    通过消息机制调用, 当子类没有initialize方法时, 会调用父类的initialize方法, 所以父类的initialize方法会调用多次

    链接:https://www.jianshu.com/p/bd2197d5e547

    相关文章

      网友评论

          本文标题:iOS 控制器生命周期

          本文链接:https://www.haomeiwen.com/subject/ayheoltx.html