我读到 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/