In the code below the print statements execute in the order of the numbers they contains (1, 2, 3, etc.)
override func viewDidLoad() {
super.viewDidLoad()
DispatchQueue.main.async {
print("4")
}
print("1")
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
DispatchQueue.main.async {
print("5")
}
print("2")
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
DispatchQueue.main.async {
print("6")
}
print("3")
}
Can you explain why execution process happens this way? Are viewWillAppear
and viewWillAppear
methods already in the queue when we asynchronously dispatch a block in viewDidLoad
?
答案 0 :(得分:9)
viewWillAppear
中异步调度块时,viewDidAppear
和viewDidLoad
方法是否已在队列中?
实际上:是的。它们并非“在队列中”,但它们已经在列车中作为现有主队列代码序列的一部分。
这完全取决于runloop何时结束。在发生这种情况之前,异步调度到主队列的代码无法运行。实际上,我们必须在print 4
之前完全结束这次CATransaction(runloop的一次“革命”),等等。
您可能已将此日志记录放入根视图控制器中。这是一种特殊情况,因为您的应用只是启动,在将makeKeyAndVisible
的调用发送到窗口之前没有任何反应。
此时viewDidLoad
被调用,viewWillAppear
被连续调用,作为对此makeKeyAndVisible
的一次调用的一部分。
因此,相同的代码仍然在主线程上运行;您的调度代码没有时间运行。因此,我们先得到print 1
和print 2
。
viewDidAppear
的情况略有不同:
如您所见,我们已不再接听makeKeyAndVisible
。但主线程仍在运行,因为我们立即转向任何事务完成块(cleanUpAfterCAFlushAndRunDeferredBlocks
)。将viewDidAppear
视为viewWillAppear
中动画的完成块可能会有所帮助。这已经被配置为viewWillAppear
调用的一部分,因此它仍然是同一事务的一部分。因此,viewDidAppear
仍然会在viewWillAppear
之后暂停,我们会print 3
。
现在最后启动序列结束,您的主队列异步代码有机会运行,它按入队顺序排列(print 4
,{{ 1}},print 5
)。