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

问题描述 投票:0回答:1

所以,在我的应用程序上,我有一个我想在每次用户返回应用程序时更新的提要。我打算在我的applicationWillEnterForegroundAppDelegate做一个例程。一切都运行正常,但有时,我的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的冻结有时只会发生。

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

ios swift grand-central-dispatch
1个回答
3
投票

将UI更新到主线程的Dispatch:

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

每当你以任何方式访问/修改UI时,在主线程上执行以避免出现意外问题(link到这个主题的几个资源之一,我建议你谷歌上去阅读更多)。

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

© www.soinside.com 2019 - 2024. All rights reserved.