Contents

两年多以前还在学校上学的时候就发现了 init 和 viewDidLoad 之间的执行顺序的有趣现象《UIViewController 的 init 和 viewDidLoad 执行顺序带来的有趣现象》,那个时候止步于表面现象的探索只观察到了 viewDidLoad 函数在某些时候会在 init 方法中穿插被执行。最近又遇到了,然后看了下调用栈再看了下文档注释,发现其实很明了。

在 init 方法中调用了 vc 的 view getter,但是由于 vc 的 view 还没有加载出来或者说第一次加载,所以转而调用了 vc 的 loadViewIfRequired 方法,在 loadViewIfRequired 内部调用了 vc 的 viewDidLoad。

随后这几个方法在栈里面依次返回栈帧退掉,就又再次进入了 init 方法体里面继续往下走了。

从 API 文档的注释里也看到很清楚。

@property(null_resettable, nonatomic,strong) UIView *view; // The getter first invokes [self loadView] if the view hasn’t been set yet. Subclasses must call super if they override the setter or getter.

如果 view 还没有被设置,这个 getter 方法会调用 [self loadView],应该就是这个方法调用的 loadViewIfRequired。

- (void)viewDidLoad; // Called after the view has been loaded. For view controllers created in code, this is after -loadView. For view controllers unarchived from a nib, this is after the view is set.

这个方法在 view 被加载之后调用。view 被加载分成用代码加载,那就是 -loadView 方法之后;如果是 nib 加载,那就是 view 被 set 之后。

Contents