让我们假设我们有一些异步代码.在某种程度上,我们必须将它包装在Task {…}中,以便从同步上下文中运行它. 那么,标准的方法在哪里呢?ViewModel还是ViewController

如果我们用ViewModel中的Task {…}包装它,ViewModel函数将变得有效地同步,并且从ViewController调用它们仍然需要所有这些完成/委托/闭包/RX skip 以在异步工作完成后完成一些UI更新.

另一方面,如果我们将ViewModel个函数标记为async,并从Task {…}主体内的ViewController调用它们,似乎就解决了问题.那么,这是一条可行的道路吗?

推荐答案

我不会重新介绍遗留的完成模式(闭包、委托等).这违背了SWIFT并发性的目的,即优雅地管理异步依赖关系.例如,在WWDC 2021视频Swift concurrency: Update a sample app中,他们展示了如何使用SWIFT并发消除完成处理程序的示例(S).

因此,将异步视图模型方法指定为async.然后,视图控制器将使用Task {…}进入SWIFT并发的异步上下文,以便它可以await视图模型的async方法,然后在完成时触发UI更新.

但是,Task {…}的使用并不局限于视图控制器.视图模型也可以使用它(例如,在需要保存任务以便可能稍后出于某种原因取消它的情况下).

但你会问:

如果我们将ViewModel个函数标记为async,并从Task {…}主体内的ViewController调用它们,似乎就解决了问题.那么,这是一条可行的道路吗?

正是如此.如果该方法确实在执行一些异步操作,则将其标记为async,视图控制器将从Task {…}中调用它.


话虽如此,在SwiftUI项目中,视图模型经常传递对具有ObservableObject@Published属性的视图的更新,我将保持这种直观和自然的模式.在这一点上,您 Select 进入异步上下文的地方就不那么令人信服了.

话虽如此,但从可测试性的Angular 来看,您仍然希望能够知道视图模型的异步任务何时完成,因此我可能仍然使用视图模型的方法async.

Swift相关问答推荐

Swift Tree实现中的弱var

防止NavigationLink自行返回导航视图

绑定到可选值的非可选属性?'

如何在SWIFT中使用DiscardingTaskGroup获得任务结果

如何偏移HStack中的视图,但仍然约束框架以与偏移匹配?

SwiftData:非法try 在不同上下文中的对象之间建立关系

如何隐藏集合视图中特定的单元格,以避免出现空白空间?

在 Swift 中将异步任务包装到 DispatchWorkItem 中以使其可取消?

在 SwiftUI 中禁用 Select 器选项

String(validatingUTF8:) 和 String(utf8String:) 之间有区别吗?

使用 WrappingHStack 文本溢出到新行

swift 是否遇到 Java 的 2gb 最大序列化大小问题?

并发执行代码中捕获的 var 的变异

SwiftUI 动画的范围

自定义 DispatchQueue 服务质量

如何自己快速编写 Hashable 协议

如果没有标记,则为 Swift 预处理器

在 Swift 中计算两个日期之间的差异

UITableViewCell 不显示 detailTextLabel.text - Swift

Swift 中的单元测试致命错误