UI(有时)在iOS上的操作期间冻结

时间:2018-02-28 13:16:02

标签: ios swift grand-central-dispatch

因此,在我的应用中,每当用户返回应用时,我都会有一个我想要更新的Feed。 我正在applicationWillEnterForeground AppDelegate @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在此操作期间冻结。 我能够使用标签找到这种情况的进展,以显示此例程的进度。标签更新了三个主要观点:

  • 开始例程之前
  • 在例程中
  • 例程结束时

有时,此工作流程运行正常,我可以通过此标签查看进度。 但有时,标签只显示第一条消息,并且不会出现在例程中发生的消息。除此之外,我无法在我的应用上做任何事情,因为用户界面被冻结了。一旦例程结束,一切都恢复正常。

这是我的应用程序为调用此例程而执行的流程的简化版本:

<baseAddresses><add baseAddress="localhost:1234/GettingStartedLib/CalculatorService.vsc"/>
</baseAddresses>

如您所见,我在全局队列中执行更新,因此我没有阻止主线程。 而且,UI的冻结有时只会发生。

有什么意义我可以看一下发现了什么?主线程是否可能被其他东西阻止?

1 个答案:

答案 0 :(得分:3)

将UI更新到主线程:

DispatchQueue.main.async { showMessage(message: "Updates completed") }

每当你以任何方式访问/修改用户界面时,都会在主线程上进行操作以避免出现意外问题(link到这个主题的多个资源之一,我建议你google up并阅读更多)。

这也适用于其余的代码,如果有与UI相关的内容,也可以为它做同样的事情 - 例如,如果在完成任务后调用tableView.reloadData,则在主要代码上执行线程也是如此。