Swift线程:何时使用DispatchQueue.main.async?

时间:2018-06-06 18:22:48

标签: swift multithreading user-interface

我相信当我调用它时,我理解调度队列正在做什么,但我不确定我应该在何时使用它以及当我使用它时它的优点是什么。

如果我的理解是正确的,DispatchQueue.main.async {// code}将调度闭包中包含的代码以异步方式在主调度队列上运行。主队列具有最高优先级,通常保留用于更新UI以最大化App响应性。

我感到困惑的是:在调度队列闭包中更新UI元素与在同一位置编写闭包外的代码有什么区别?在视图体中执行代码加载方法而不是将其发送到调度队列是否更快?如果没有,为什么?

代码示例:

class MyViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        updateUI()
    }

}

对战:

class MyViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        DispatchQueue.main.async {
            updateUI()
        }
    }
}

哪一个会更快地更新用户界面?

2 个答案:

答案 0 :(得分:7)

DispatchQueue.main.async的主要用途是当您在后台队列上运行代码并且需要在主队列上执行特定代码块时。

在您的代码中,viewDidLoad已在主队列上运行,因此没有理由使用DispatchQueue.main.async

但使用它并不一定是错的。但它确实改变了执行的顺序。

没有示例:

class MyViewController: UIViewController {
    func updateUI() {
        print("update")
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        print("before")
        updateUI()
        print("after")
    }
}

正如人们所料,输出将是:

  

之前
  更新
  之后

现在添加DispatchQueue.main.async

class MyViewController: UIViewController {
    func updateUI() {
        print("update")
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        print("before")
        DispatchQueue.main.async {
            updateUI()
        }
        print("after")
    }
}

输出变化:

  

之前
  
后   更新

这是因为异步闭包在当前runloop完成后排队等待运行。

答案 1 :(得分:0)

我只是遇到了您的问题中所述的确切情况:viewDidLoad()打电话给DispatchQueue.main.async

就我而言,我想在显示视图之前修改情节提要的默认设置。

但是,当我运行该应用程序时,默认的Storyboard项会暂时显示。动画的segue将完成。而且只有THEN才能通过viewDidLoad()中的代码修改UI组件。因此,在编辑真实值之前,所有默认情节提要板值都有这种烦人的闪光。

这是因为我正在通过总是首先分派到主线程的辅助函数来修改那些控件。该发件为时已晚,无法在控件首次显示之前对其进行修改。

所以:在viewDidLoad()中修改Storyboard UI,而不会分派到主线程。如果您已经在主线程上,请在那里进行工作。否则,您最终的异步调度可能为时已晚。