当更新我的 UI 以响应异步操作时,我应该在哪里调用 DispatchQueue?

Posted

技术标签:

【中文标题】当更新我的 UI 以响应异步操作时,我应该在哪里调用 DispatchQueue?【英文标题】:When updating my UI in response to an async action, where should I call DispatchQueue? 【发布时间】:2018-09-27 21:43:58 【问题描述】:

在我的 ios 应用程序中,我提出了很多网络请求。当这些请求成功/失败时,会触发视图控制器中的委托方法。委托方法包含负责更新 UI 的代码。在以下示例中,didUpdate(foo:) 是委托方法,presentAlert(text:) 是我的 UI 更新。

没有DispatchQueue,代码会变成这样:

func didUpdate(foo: Foo) 
  self.presentAlert(text: foo.text)


func presentAlert(text: String) 
  let alertController = ...

  self.present(alertController, animated: true)

当谈到使用DispatchQueue 来确保我的 UI 将快速更新时,我开始失去判断代码中实际发生的情况的能力。下面两种实现有什么区别吗?

第一种方式:

func didUpdate(foo: Foo) 
  self.presentAlert(text: foo.text)


func presentAlert(text: String) 
  let alertController = ...

  DispatchQueue.main.async 
    self.present(alertController, animated: true)
  

第二种方式:

func didUpdate(foo: Foo) 
  DispatchQueue.main.async 
    self.presentAlert(text: foo.text)
  


func presentAlert(text: String) 
  let alertController = ...

  self.present(alertController, animated: true)

我采用哪种方法重要吗?似乎在 presentAlert 函数中包含 DispatchQueue 块更好,所以我不必在任何时候都包含 DispatchQueue.main.async 来调用 presentAlert

是否仅当您(或您正在使用的框架)将自己“移动”到后台队列时才需要显式发送块到主队列?

如果有任何外部资源可以帮助我理解 GCD,请告诉我!

【问题讨论】:

【参考方案1】:

我采用哪种方法重要吗?似乎在 presentAlert 函数中包含 DispatchQueue 块更好,所以我不必在任何时候都包含 DispatchQueue.main.async 来调用 presentAlert?

这两种方法没有区别。但是,正如您所说,第二种方法的缺点是您必须将所有对 presentAlert 的调用包装在 DispatchQueue.main.async 闭包周围。

仅当您(或您正在使用的框架)将自己“移动”到后台队列中时,是否只需要显式地将块发送到主队列?

如果你的问题是如果你从主队列分派到主队列是否会有问题,那么答案是否定的。如果你在主队列中异步调度主队列,它所做的只是稍后在运行循环中调用你的方法。

如果有任何外部资源可以帮助我理解 GCD,请告诉我!

互联网上有很多资源可以更好地理解 GCD。看看这个Raywenderlich tutorial。这是一个很好的起点。

我的建议是,如果您有一个处理所有 Web 服务调用的中心类,那么在获得 Web 服务响应后解析数据后,最好在主队列上调用完成回调闭包。这样,您就不必在视图或视图控制器类中一直调度到主队列。

【讨论】:

以上是关于当更新我的 UI 以响应异步操作时,我应该在哪里调用 DispatchQueue?的主要内容,如果未能解决你的问题,请参考以下文章

Android异步任务AsyncTask

使用 Relay 的嵌套表单组件 UI 中的状态应该在哪里?

根据 API 的响应异步更新进度条

收到异步 POST 响应,需要更新网页

DeprecationWarning:不推荐调用不带回调的异步函数。 - 如何找到“功能:”在哪里?

异步任务(AsyncTask)