所以,在我的应用程序上,我有一个我想在每次用户返回应用程序时更新的提要。我打算在我的applicationWillEnterForeground
的AppDelegate
做一个例程。一切都运行正常,但有时,我的UI在此操作期间冻结。我能够使用标签找到这种情况的进展,以显示此例程的进度。标签更新了三个主要观点:
有时,这个工作流程工作正常,我能够通过这个标签看到进展。但有时,标签只显示第一条消息,并且不会出现在例程中发生的消息。除此之外,我在我的应用程序上无法做任何事情,因为UI被冻结了。一旦例程结束,一切都恢复正常。
这是我的应用程序为调用此例程而执行的流程的简化版本:
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
let mainViewController = MainViewController()
func applicationWillEnterForeground(_ application: UIApplication) {
mainViewController.refreshLatestVideos()
}
}
class MainViewController: UITabBarController {
private var subscriptionsController: SubscriptionsController! // initialized on viewDidLoad
func refreshLatestVideos() {
subscriptionsController.refreshLatestVideos(sender: nil)
}
}
class SubscriptionsController: UITableViewController {
private var subscriptionsModelController: SubscriptionsModelController! // received on constructor
@objc func refreshLatestVideos(sender:UIButton!) {
showMessage(message: "Updating subscriptions...") // this message is always shown to me
subscriptionsModelController.loadLatestVideos()
}
}
class SubscriptionsModelController {
func loadLatestVideos() {
UIApplication.shared.isNetworkActivityIndicatorVisible = true
DispatchQueue.global(qos: .userInitiated).async {
// bunch of requests with Just
...
// update message
showMessage(message: "Updating subscription x of y") // this message sometimes doesn't appear, because the UI is frozen
// another requests
...
// update message
showMessage(message: "Updates completed")
}
}
}
如您所见,我正在全局队列中执行更新,所以我没有阻止主线程。而且,UI的冻结有时只会发生。
有什么意义我可以看看发生了什么?主线程是否可能被其他东西阻止?
将UI更新到主线程的Dispatch:
DispatchQueue.main.async { showMessage(message: "Updates completed") }
每当你以任何方式访问/修改UI时,在主线程上执行以避免出现意外问题(link到这个主题的几个资源之一,我建议你谷歌上去阅读更多)。
这也适用于其余的代码,如果有与UI相关的东西,也可以为它做同样的事情 - 例如,如果在完成任务后调用tableView.reloadData
,也可以在主线程上执行。