代码之家  ›  专栏  ›  技术社区  ›  Mike

如何调度。主要的异步“更新UI”?

  •  0
  • Mike  · 技术社区  · 7 年前

    我已经使用Swift有一段时间了,GCD仍然让我有点困惑。

    我读过:

    https://www.raywenderlich.com/60749/grand-central-dispatch-in-depth-part-1

    https://developer.apple.com/documentation/dispatch

    我理解GCD允许在不同线程上运行多个任务的总体概念(我认为这是对的)。

    我不太明白的是 Dispatch.main.async “更新用户界面”。

    例如,如果我在某个地方调用一个api并返回数据,比如说返回所有数据需要5秒钟,那么如何使用 派遣主要的异步 帮助更新用户界面?怎么做 派遣主要的异步 知道要更新的UI吗?

    我仍然不太明白GCD的位置,为什么不能使用某种观察者、委托或闭包,在加载所有数据时调用它们?

    如果我正在进行api调用,但没有立即使用数据,例如,只是将数据存储在一个数组中,直到我决定使用它,那么是否需要使用GCD来“更新UI” 派遣主要的异步 ?

    我已经使用firebase/firestore作为db有一段时间了。Firebase有自己的侦听器并异步运行。关于:在iOS/Swift中处理firebase异步返回的最佳方法,我仍然无法得到一个很好的答案。例如,当我的应用程序加载时,如果我去firebase获取数据以填充tableviewcontroller,那么知道所有数据何时返回的最佳方法是什么?我一直在用一名代表来做这件事,但想知道是否以及如何做 派遣主要的异步 可以使用。

    2 回复  |  直到 7 年前
        1
  •  6
  •   Codo    7 年前

    Dispatch.main.async 没有 更新UI . 故事的发展方向不同:如果你想 使现代化 用户界面,您必须从 主要的 线如果当前代码未在主线程上运行, 派遣主要的异步 是在 主要的 线

    这是一个影响大多数操作系统的旧限制:与UI相关的操作,例如更改UI中的元素,必须只能从特定线程调用,通常是所谓的 主要的 线

    在许多情况下,这不是问题,因为用户界面相关的代码通常在某些用户界面事件(用户单击或点击、按键等)触发时起作用。这些事件回调发生在主线程上。因此没有线程问题。

    使用GCD,您可以在不同的线程上运行长时间运行的任务,这样任务就不会减慢甚至阻塞UI。因此,当这些任务完成后,您想要更新UI(例如,显示结果),您必须在主线程上这样做。具有 派遣主要的异步 您可以要求GCD在主线程上运行一段代码。GCD不知道用户界面。您的代码必须知道要更新什么。GCD只是在所需的线程上运行代码。

    如果在任务结束时,UI中没有任何可显示或更新的内容,则无需调用 派遣主要的异步 .

    更新Firebase

    Firebase数据库客户端在单独的后台线程中执行所有网络和磁盘操作 主线。

    Firebase数据库客户端调用对代码的所有回调 在…上 主线。

    所以不需要打电话 派遣主要的异步 在Firebase回调中。你已经在主线上了。

        2
  •  2
  •   Josh Homann    7 年前

    仅供参考,所有UI代码都需要在主线程上运行的原因是,绘图是一个(相对CPU时间而言)漫长而昂贵的过程,涉及许多数据结构和数百万像素。图形代码在执行帧更新时基本上需要锁定所有UI资源的副本,因此您不能在绘制过程中编辑这些资源,否则,如果在系统渲染这些对象的过程中进行了一半的更改,就会出现wierd瑕疵。由于所有绘图代码都在主线程上,因此系统可以阻止主线程,直到渲染完成,因此在当前帧完成之前,不会处理任何更改。此外,由于一些图形是缓存的(基本上渲染为纹理,直到您调用setNeedsDisplay或setNeedsLayout之类的东西),如果您尝试从后台线程更新某些内容,则完全有可能它不会显示并导致不一致的状态,这就是为什么您不应该在后台线程上调用任何UI代码。