UIViewController 生命周期

2,808 阅读2分钟

前言

UIViewController 往往是 iOS 页面开发的基础,用户交互和数据展示都是由它来控制,了解了它的生命周期,就能做到:在合适的时机,做合适的事情

顺序

下面对 UIViewController 的每个生命周期函数进行一个打印,确定它们的执行顺序。

@implementation ViewController

- (void)loadView
{
    [super loadView];
    NSLog(@"%@", NSStringFromSelector(_cmd));
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    NSLog(@"%@", NSStringFromSelector(_cmd));
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    NSLog(@"%@", NSStringFromSelector(_cmd));
}

- (void)viewWillLayoutSubviews
{
    [super viewWillLayoutSubviews];
    NSLog(@"%@", NSStringFromSelector(_cmd));
}

- (void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];
    NSLog(@"%@", NSStringFromSelector(_cmd));
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    NSLog(@"%@", NSStringFromSelector(_cmd));
}

@end

含义

- loadView

此时,控制器的 view 还未初始化,可以通过重写这个方法自定义控制器的 View,如果这样做,那就不能调用[super loadView](上面代码调用是为了方便打印,不然屏幕就是黑的)。

- viewDidLoad

在控制器的生命周期中,它只会被调用一次,此时,view 已经初始化好,非常适合做一些页面的初始化任务。

- viewWillAppear

它会在控制器的视图将要出现在屏幕中时被调用,在控制器生命周期中可能会被调用多次。在此处,适合做一些与视图出现相关联的任务,例如改变状态栏的方向、风格。

- viewWillLayoutSubviews

当 view 的子视图即将布局时,此方法会被调用,触发的条件是:

  • view 被添加到视图层次中
  • view 的 bounds 发生了改变
  • 调用了 - setNeedsLayout 方法
  • 调用了 - layoutIfNeeded 方法

这个方法是写 frame 布局代码的好地方,将 view 的子视图布局好,每次 view 大小发生改变时,其子视图布局也会相应改变。

- viewDidLayoutSubviews

当 view 的子视图已经布局时,此方法会被调用,触发条件同上。

- viewDidAppear

它会在控制器的视图出现在屏幕后被调用,此时,view 的 bounds 已经确定,不过在这里写布局相关代码,可能会反映到屏幕上。

- viewWillDisappear

视图即将从屏幕中消失时触发。

- viewDidDisppear

视图从屏幕中消失后触发。

问题

1、上面测试代码中,- viewWillLayoutSubviews 方法打印了两次?

答:因为 view 被添加到视图层次中会触发一次,view 的 bounds 改变还会触发一次。

2、有控制器 A、B,从 A push 到 B,是 A 的 - viewDidDisappear 先触发,还是 B 的 - viewWillAppear 先触发?

答:B。