【问题标题】:how ios UI update code defined for use with main dispatchios UI 更新代码如何定义用于主调度
【发布时间】:2019-04-17 03:15:48
【问题描述】:

我已经阅读了很多示例代码,我知道通常您希望 更新您的 UI 的代码 在主线程上执行。如果我错过了什么,xcode 会在运行时抱怨。只是有时而已。

那么更新您的用户界面的代码实际上是如何定义的? 是否显示更新 UI 的警报?在 UITableView 上调用 reloadData()?简单地设置 UILabel 的文本怎么样? 特别是对于这三个,我一直在我的应用程序中以两种方式看到和使用它,并且无法真正找出规则。特别是因为 xcode 让我可以摆脱这两种情况......有时。

编辑:哦,我明白我的困惑来自哪里。我以为你在哪个线程上是随机的。但是你实际上“总是”在主线程上,除非你做一些类似任务的事情,它在后台线程上运行。

所以主线程检查器实际上并没有让我“逃脱”使用 reload() 和错误地更改我的 viewController 中的标签。只是保证我在主线程上。

我以为我不得不突然将每个标签更改都包含在 dispatch.async 中。

【问题讨论】:

  • 如果屏幕上的某些内容发生了变化,它就是在更新 UI。几乎所有以UI 开头的课程都需要在主队列中。很少有例外。
  • 用户界面或 UI 基本上是您在屏幕/视口上看到的任何东西。它可以是一个标签。它可以是表格视图。它可以是一个按钮。现在,如果与它们相关的任何值正在发生变化。例如。标签的文本,表格视图的内容,按钮的颜色,这称为更新 UI,Apple 建议在主线程上完成。如果不是,那么它会使您的应用程序看起来冻结,从而延迟本应立即执行的更改。这相当于糟糕的用户体验。

标签: ios swift multithreading user-interface grand-central-dispatch


【解决方案1】:

Xcode 你做某事并不意味着你应该做那件事。

重新加载表格视图、显示警报和更改标签文本都是 UI 更新。它们都会改变您在屏幕上看到的内容,因此它们是 UI 更新。始终在主线程上执行这些操作。

不属于 UI 更改的事情:发送 HTTP 请求、处理数字、从某个数据库加载数据。它们不会改变您在屏幕上看到的内容。

【讨论】:

    【解决方案2】:

    您必须在主线程上更新您的 UI,以便用户在与您的 UI 交互时不会感到一些延迟或干扰。即重新加载表格、更改文本、更改颜色等。

    您可以在后台线程上执行您的耗时操作,以便您的应用在操作期间表现良好。即 HTTP 请求、数据库操作、长时间运行的循环、大型嵌套条件等。

    你可以这样写你的代码....

    // define these methods in your helper class or wherever you want.
    public func BACKGROUND_QUEUE(_ codeBlock:@escaping (() -> Void)) -> Void {
        return DispatchQueue.global(qos: DispatchQoS.QoSClass.background).async(execute: codeBlock)
    }
    
    public func MAIN_QUEUE(_ codeBlock:@escaping (() -> Void)) -> Void {
        return DispatchQueue.main.async(execute: codeBlock)
    }
    

    并像这样使用。

    func fetchData() {
    
        BACKGROUND_QUEUE {
            //your http request to get some text
            let text = yourResult
            MAIN_QUEUE {
                textLabel.text = text
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      “仅在主线程上更新 UI”的规则仅涵盖了部分事实,最好坚持 UIKit documentation 声明的内容:

      重要
      仅在应用程序的主线程或主线程中使用 UIKit 类 调度队列,除非另有说明。这个限制 特别适用于从 UIResponder 派生的类或 涉及以任何方式操纵应用的用户界面。

      此限制不仅适用于呈现给用户的(可见)更新,也适用于任何 UIKit 类,除非另有说明。

      例如,访问应用程序委托不会影响 UI,但在非主线程上这样做会导致“主线程检查器违规”:

      DispatchQueue.global().async {
          let shared = UIApplication.shared.delegate
      }
      
      // Main Thread Checker: UI API called on a background thread: -[UIApplication delegate]
      

      【讨论】:

        猜你喜欢
        • 2015-03-15
        • 1970-01-01
        • 1970-01-01
        • 2018-10-16
        • 2012-11-17
        • 2015-03-27
        • 2015-02-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多