探究 UIViewController 生命周期—swift

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

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


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。

 

测试样例说明

(1)ViewController 是首页视图控制器,我们将里面所有的与生命周期有关的函数都打印出来。
(2)同时 ViewController 中添加了一个“跳转”按钮,点击后跳转到另一个视图控制器(AnotherViewController)。
(3)AnotherViewController 里有个“返回”按钮,点击又会回到前一个页面。

 

测试代码 :

(1)ViewController.swift

class ViewController: UIViewController {
    // 加载视图时会调用该方法
    override func loadView() {
        super.loadView()
        print("loadView,加载视图")
    }
    
    // 当加载视图结束时调用该方法
    override func viewDidLoad() {
        super.viewDidLoad()
        print("viewDidLoad,加载视图结束")
        
        let button:UIButton = UIButton(type:.system)
        button.frame = CGRect(x: 10, y: 50, width: 100, height: 30)
        button.setTitle("跳转", for: .normal)
        button.addTarget(self, action:#selector(jump) , for: .touchUpInside)
        self.view.backgroundColor = UIColor.orange
        self.view.addSubview(button)
        
    }
    
    // 视图将要显示时调用该方法
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        print("viewWillAppear,视图即将显示")
    }
    
    // 当视图已经显示时调用该方法
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        print("viewDidAppear,视图已经显示")
    }
    
    // 当视图将要消失时调用该方法
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        print("viewWillDisappear,视图即将消失")
    }
    
    // 当时图已经消失时调用该方法
    override func viewDidDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        print("viewDidDisappear,视图已经消失")
    }
    
    // 当接收到内存警告时会执行这个方法
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
    
  
    
    @objc func jump(){
        print("点击按钮,开始跳转!")
        let anotherVC = anotherViewController()
        present(anotherVC, animated: true, completion: nil)
    }
}

AnotherViewController.swift

class anotherViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
         //创建返回按钮
        let  button:UIButton = UIButton(type: .system)
        button.frame = CGRect(x: 10, y: 150, width: 100, height: 30)
        button.setTitle("返回", for: .normal)
        button.addTarget(self, action: #selector(back), for: .touchUpInside)
        self.view.backgroundColor = UIColor.green
        self.view.addSubview(button)
    }
    //返回之前视图
    @objc func back(){
        print("点击按钮,开始返回!")
        self.dismiss(animated: true, completion: nil)
    }

}

 

运行测试
我们从 ViewController 跳到 AnotherViewController,再从 AnotherViewController 跳回 ViewController。整个控制台打印出来的流程如下:

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值