Execution order of async tasks on the main queue

时间:2017-12-24 16:24:36

标签: ios swift grand-central-dispatch

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?

1 个答案:

答案 0 :(得分:9)

  

viewWillAppear中异步调度块时,viewDidAppearviewDidLoad方法是否已在队列中?

实际上:是的。它们并非“在队列中”,但它们已经在列车中作为现有主队列代码序列的一部分。

这完全取决于runloop何时结束。在发生这种情况之前,异步调度到主队列的代码无法运行。实际上,我们必须在print 4之前完全结束这次CATransaction(runloop的一次“革命”),等等。

您可能已将此日志记录放入根视图控制器中。这是一种特殊情况,因为您的应用只是启动,在将makeKeyAndVisible的调用发送到窗口之前没有任何反应。

此时viewDidLoad被调用,viewWillAppear被连续调用,作为对此makeKeyAndVisible的一次调用的一部分。

enter image description here

enter image description here

因此,相同的代码仍然在主线程上运行;您的调度代码没有时间运行。因此,我们先得到print 1print 2

viewDidAppear的情况略有不同:

enter image description here

如您所见,我们已不再接听makeKeyAndVisible。但主线程仍在运行,因为我们立即转向任何事务完成块(cleanUpAfterCAFlushAndRunDeferredBlocks)。将viewDidAppear视为viewWillAppear中动画的完成块可能会有所帮助。这已经被配置为viewWillAppear调用的一部分,因此它仍然是同一事务的一部分。因此,viewDidAppear仍然会在viewWillAppear之后暂停,我们会print 3

现在最后启动序列结束,您的主队列异步代码有机会运行,它按入队顺序排列(print 4,{{ 1}},print 5)。