主队列异步任务的执行顺序

Execution order of async tasks on the main queue

在下面的代码中,打印语句按照它们包含的数字(1、2、3 等)的顺序执行

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")
}

你能解释一下为什么执行过程会这样吗?当我们在 viewDidLoad 中异步调度一个块时,viewWillAppearviewWillAppear 方法是否已经在队列中?

Are viewWillAppear and viewDidAppear methods already in the queue when we asynchronously dispatch a block in viewDidLoad?

实际上:是的。确切地说,它们不是 "in the queue",但它们已经作为现有主队列代码序列的一部分在训练中。

这完全取决于 运行 循环何时结束。在这种情况发生之前,您异步分派到主队列的代码不能 运行 。实际上,我们必须在 print 4 等发生之前完全结束此 CATransaction(运行 循环中的一个 "revolution")。

您可能已将此日志记录放入根视图控制器中。这是一种特殊情况,因为您的应用程序刚刚启动,在对 makeKeyAndVisible 的调用发送到 window.

之前没有任何反应

在那一刻,viewDidLoad 被调用,viewWillAppear 被连续调用,作为对 makeKeyAndVisible.

的调用的一部分

因此,相同的代码仍在主线程上 运行ning;没有时间将您的代码发送到 运行。所以我们先得到 print 1print 2

viewDidAppear的情况有点不同:

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

现在 启动序列终于结束了,你的主队列异步代码有机会 运行,它按照它入队的顺序执行(print 4, print 5, print 6).