今天写项目的时候发现了一个非常奇怪的问题,我一度认为可能是我的 Xcode 出了 bug。
先来猜猜下面代码的执行顺序?
这是一段非常常见的代码,很多 controller 都是这么写的。
正常来说执行顺序肯定是 1、2、3、4 无疑。然而事实上,执行顺序却是:1、3、4、2。
这就导致了一个问题:viewModel 请求不到数据,因为走到第 4 步的时候,viewModel 还没有被初始化,此时它是 nil。
如下图所示:
从控制台中我们可以看到,最下面的 _viewModel = nil。而且当走完第 4 步后,程序竟然又回到了第 2 步。
起初我以为这是一个 Xcode 本身的 bug,因为它实在是太奇怪了。后来我才知道,原来是因为 viewDidLoad 被提前调用了。
viewDidLoad 方法一般只会在 nib 文件已载入内存,也就是视图树构建完成之后调用。
但是如果 controller 的 view 属性被使用时为 nil,就会导致 nib 的加载,从而导致 viewDidLoad 的调用。
对于本文来说,我们在初始化方法中写了 self.view.backgroundColor = xxx; 这句话本身并没有任何错误,但是它导致了 viewDidLoad 的提前调用,因此就出现了文章开头提到的情况,执行顺序变成了 1、3、4、2。
最后我的解决办法是,把成员变量 _viewModel 的初始化放到 viewDidLoad 里。这又是为什么呢?具体内容可以参考这篇文章:iOS 开发中的争议(一)类的成员变量应该如何定义?
大部分的类成员变量都需要在类初使化方法中赋值,大部分的 UIViewController 的成员变量,都需要在 viewDidLoad
方法中赋值。