ios - Swift:更新 UI - 主线程上的整个功能或只是 UI 更新?

标签 ios swift multithreading user-interface

我读到 UI 应该始终在主线程上更新。但是,当谈到实现这些更新的首选方法时,我有点困惑。

我有各种函数可以执行一些条件检查,然后使用结果来确定如何更新 UI。我的问题是整个函数应该在主线程上运行吗?应该只更新 UI 吗?我可以/应该在另一个线程上运行条件检查吗?这取决于函数的作用或您希望它完成的速度吗?

示例一个无需线程即可更改 ImageView 内图像的函数:

@IBAction func undoPressed(_ sender: Any) {
        if !previousDrawings.isEmpty {
            previousDrawings.remove(at: previousDrawings.count - 1)
            if let lastDrawing = previousDrawings.last {
                topImageView.image = lastDrawing
            }
            else {
                // empty
                topImageView.image = nil
            }
        }
    }

我应该在主线程上设置 topImageView.image 吗?像这样:

 @IBAction func undoPressed(_ sender: Any) {
        if !previousDrawings.isEmpty {
            previousDrawings.remove(at: previousDrawings.count - 1)
            if let lastDrawing = previousDrawings.last {
                DispatchQueue.main.async {
                    self.topImageView.image = lastDrawing
                }
            }
            else {
                DispatchQueue.main.async {
                    self.topImageView.image = nil
                }
            }
        }
    }

我应该使用后台线程进行条件检查吗?像这样:

@IBAction func undoPressed(_ sender: Any) {
        DispatchQueue.global(qos: .utility).async {
            if !previousDrawings.isEmpty {
                previousDrawings.remove(at: previousDrawings.count - 1)
                if let lastDrawing = previousDrawings.last {
                    DispatchQueue.main.async {
                        self.topImageView.image = lastDrawing
                    }
                }
                else {
                    DispatchQueue.main.async {
                        self.topImageView.image = nil
                    }
                }
            }
        }
    }

如果有人可以解释首选哪种方法以及为什么这真的很有帮助。

最佳答案

备份。除特殊情况外,所有您的代码都在主线程上运行。例如,UIAction 方法总是在主线程上执行,UIViewController 及其各种子类定义的所有方法也是如此。事实上,您可以有把握地说 UIKit 方法是在主线程上执行的。同样,您的方法只会在非常特殊的情况下在后台线程上调用,这些情况都有详细记录。

您可以使用 GCD 在后台线程上运行代码块。在这种情况下,代码将在后台线程上运行,因为您明确要求这样做。

某些系统函数(如 URLSession)默认调用它们的委托(delegate)方法/在后台线程上运行它们的完成处理程序。这些都有据可查。对于像 AlamoFire 或 FireBase 这样的第三方库,您必须阅读文档,但是在后台线程上调用的任何代码都应该有很好的文档记录,因为您必须对在后台线程上运行的代码采取特殊的预防措施。

使用后台线程的通常原因是长时间运行的任务可以运行到完成,而不会在完成之前卡住用户界面。

例如,一个常见的模式是使用 URLSession 从远程服务器读取一些 JSON 数据。完成处理程序在后台线程上调用,因为它可能需要时间来解析您返回的数据。但是,一旦完成解析,您将在对主线程的 GCD 调用中包装更新 UI 的调用,因为 UI 更改必须在主线程上执行。

关于ios - Swift:更新 UI - 主线程上的整个功能或只是 UI 更新?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48102035/

相关文章:

ios - Swift:使用 Device Motion 的 360 度图像

Swift:仅对最后选定的单元格将复选标记切换为 ON - 不起作用

ios - 我的网址没有响应

ios - Cloudkit 与结合

multithreading - 如何在不使用线程池执行器的情况下在单独的线程上异步执行可调用任务?

java - 在 Java 多线程环境中分配唯一代理

ios - 使用未解析的标识符 : "UNMutableNotificationContent"

ios - Objective C 从数组 [i] 中获取字典

ios - Realm 同步数据在应用程序重新安装时重置

c# - 在 Silverlight 中,如何知道代码是否在 UI 线程中运行?