繁体   English   中英

嵌套DispatchQueue.main.async

[英]Nested DispatchQueue.main.async

我正在从VC调用的函数中显示警报。 我不希望主VC被阻止。 我正在异步调用此警报功能。 该函数又具有另一个异步。 这是好的做法,还是我做错了?

有人可以建议遵循以下代码的良好做法吗?

class MyVC: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Don't block main thread
        DispatchQueue.main.async {
            self.showAlert(title: "Title", message: "Message")
        }

        // Do other stuff ...

    }
}

func showAlert(title: String = "", message: String) {

    alert = UIAlertController(title: title,message: message, preferredStyle: .alert)
    let cancelAction = UIAlertAction(title: "Ok", style: .cancel, handler: nil)
    alert.addAction(cancelAction)

    DispatchQueue.main.async {
        UIApplication.shared.keyWindow?.rootViewController!.present(alert, animated: true, completion: nil)
    }
}

显示警报不会阻塞线程。 present(_:animated:completion:)不是阻塞操作,因此没有理由添加任何这些.async调用。

就是说,您不想尝试在viewDidLoad内部显示警报。 还为时过早。 您的视图控制器尚未显示在屏幕上。 您应该将showAlert()放在viewDidAppear ,并删除所有.async调用。

作为一般规则,在任何情况下,尤其是在视图控制器出现在屏幕上时,此类模式警报都应是最后的手段。 通常,您应该将要呈现给用户的任何消息集成到视图本身,而不是阻塞整个UI。 但是,如果警报是适当的(有时是警报),那么只要在主队列中就可以直接显示警报。

看来您有DispatchQueue问题:)

您的程序在运行时使用操作队列。 该队列可以是系统定义的(例如main )或用户定义的。 使用DispatchQueue.main.async(_:) ,会将代码块排队到主队列中。 时间到了,主队列执行它们。

但是在viewDidLoad(_:) ,您已经在main队列中。 另外,调用AlertController是UI操作,除了main之外,不能在任何队列上执行UI操作,您不需要将代码块发送到任何队列,也不需要。

而且,就像@ SeanRobinson159所说的那样, AlertController在屏幕上时不会阻止主线程。 它的工作方式与您的ViewControllers

因此,在哪些情况下应使用DispatchQueue调用AlertController

您应该使用DispatchQueue.main.async(_:)将执行UI操作(如调用AlertController或更改UILabel的文本)的代码块从其他队列发送到主队列。 例如,也许您从事网络运营。 您在不同的线程中进行操作,并且在结果出现时,可以将进行UI操作的代码块发送到主队列。

您可以通过Google GCD(中央调度)获取详细信息。

您应该只把你有什么对主线程。 因此,您不应将其包装在viewDidLoad函数的main.async块中。

您应该将它包装在具有不同优先级的DispatchQueue

DispatchQueue.global(qos: .userInitiated).async { }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM