DispatchQueue.sync与DispatchQueue.async

时间:2019-02-12 11:37:57

标签: ios swift grand-central-dispatch

我试图了解调度同步和调度异步,我知道它以GCD的同步和异步方式执行。但是当我尝试下面的代码时,它给了我奇怪的情况。

我在Playground和Sync块中执行了3次测试以下代码,而async块给出了NSException。

//:基于UIKit的Playground,用于呈现用户界面

import UIKit
import PlaygroundSupport

class MyViewController : UIViewController {
    override func loadView() {
        let view = UIView()
        view.backgroundColor = .white

        let que = DispatchQueue.init(label: "testing")
        // Executed 3 times
        que.sync {
            for i in 0...10 {
                print(i)
            }
        }
        // Giving me NSException
        que.async {
            let label = UILabel()
            label.frame = CGRect(x: 150, y: 200, width: 200, height: 20)
            label.text = "Hello World!"
            label.textColor = .black

            view.addSubview(label)
            self.view = view
            print("Label Added to Text View")
        }
    }
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()

为什么要执行3次同步块。以及为什么会出现NSException错误。

1 个答案:

答案 0 :(得分:2)

同步将停止当前线程,直到完成您分配给它的任务。

异步将继续当前线程,并在当前线程之后或之后执行任务。

为什么会有意外的行为?

这是因为loadView()希望在执行后将UIView分配给view属性,而您正在使用async进行操作,它将在loadView完成后执行。

该异常可能是因为您没有按时分配UIView,或者是因为您正在私有队列中处理UI。用户界面应始终在主线程中处理。

您的变量que是一个私有队列,并且由于未指定否则它指向后台线程。

像这样编辑代码可能会帮助您:

import UIKit
import PlaygroundSupport

class MyViewController : UIViewController {
    override func loadView() {
        let view = UIView()
        view.backgroundColor = .white

        let que = DispatchQueue.init(label: "testing")
        // Executed 3 times
        que.sync {
            for i in 0...10 {
                print(i)
            }
        }
        // Giving me NSException
        DispatchQueue.main.async {
            let label = UILabel()
            label.frame = CGRect(x: 150, y: 200, width: 200, height: 20)
            label.text = "Hello World!"
            label.textColor = .black

            view.addSubview(label)

            print("Label Added to Text View")
        }
        self.view = view
    }
}

// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()