При попытке обновить элементы управления пользовательского интерфейса из замыкания DispatchQueue.main.async, которое выполняет некоторую обработку и занимает несколько сотен миллисекунд или более, возникает задержка в обновлении меток пользовательского интерфейса от нескольких до нескольких секунд. Если задержки нет или задержка короткая, обновление меток в пользовательском интерфейсе происходит по мере запуска кода и кажется мгновенным.
У меня есть этот небольшой пример, чтобы проиллюстрировать проблему, когда я добавил функцию «ожидание в миллисекундах», чтобы имитировать время обработки и показать задержку обновления пользовательского интерфейса.
В примере для параметра waitForMilliSecs установлено значение 300 или меньше, метки обновляются мгновенно. Любое число больше 300 приводит к задержке обновления меток от нескольких до многих секунд. Сообщения журнала указывают на то, что код запущен, и в идеале пользовательский интерфейс должен обновляться по мере их вывода на печать.
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-страницу для данных, а затем обновляю пользовательский интерфейс некоторым содержимым страницы. Обработчик завершения вызывается из URLSession.shared.dataTask в фоновом потоке, поэтому замыкание DispatchQueue.main.async используется для обновления пользовательского интерфейса в основном потоке.
Есть ли лучший способ обновить пользовательский интерфейс? Есть ли способ принудительно обновить события в основном потоке?