尝试从 DispatchQueue.main.async 闭包更新 UI 控件,该闭包执行一些处理并需要几百毫秒或更长时间,UI 标签的更新会有几秒到几秒的延迟。如果没有延迟或延迟很短,则 UI 中的标签会随着代码的运行而更新,并且似乎是瞬时的。
我有这个小例子来说明我添加了一个“毫秒等待”函数来模拟处理时间并显示发生的 UI 更新滞后的问题。
在示例中,waitForMilliSecs 设置为 300 或更少,标签会立即更新。任何大于 300 的数字,都会出现更新标签几秒到几秒的延迟。日志消息表明代码已经运行,理想情况下应该在打印出来时更新 UI。
class ViewController: UIViewController {
@IBOutlet weak var label1: UILabel!
@IBOutlet weak var label2: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
DispatchQueue.main.async {
os_log("before")
self.label1.text = "updated label 1 1111"
self.label2.text = "updated label 2 2222"
self.waitForMilliSecs(MilliSecs: 300)
os_log("after")
}
}
func waitForMilliSecs(MilliSecs millisecs: Int) -> Void {
var date = NSDate()
let firstTime = Int64(date.timeIntervalSince1970 * 1000)
var currentTime = firstTime
while currentTime - firstTime < millisecs {
date = NSDate()
currentTime = Int64(date.timeIntervalSince1970 * 1000)
}
}
真正的用例是我正在抓取 HTML 页面的数据,然后使用页面的一些内容更新 UI。完成处理程序是从后台线程上的 URLSession.shared.dataTask 调用的,因此 DispatchQueue.main.async 闭包用于更新主线程上的 UI。
有没有更好的方法来更新 UI?有没有办法强制更新主线程上的事件?