在组合中收到多个 ObservableObject 属性更改的通知

Posted

技术标签:

【中文标题】在组合中收到多个 ObservableObject 属性更改的通知【英文标题】:Be Notified of Multiple ObservableObject Property Changes in Combine 【发布时间】:2021-02-19 04:47:20 【问题描述】:

我有一个 Swift Combine 问题。假设我有一个ObservableObject,它有一些这样的属性:

class AppState: ObservableObject
  static let shared = AppState()
  @Published var a: Object?
  @Published var b: Object?
  @Published var c = [Object]()

我知道如果单个对象发生如下变化,我会收到通知:

myCancellable = AppState.shared.$a.sink  a in
  //Object 'a' changed

但是有没有办法观察多个属性并在其中任何一个发生变化时做出响应?

类似:

myCancellable = AppState.shared.[$a, $b, $c].sink  a, b, c in
  //Objects 'a', 'b', or 'c' changed

【问题讨论】:

【参考方案1】:

可能的变体是观察整个对象的任何已发布更改,例如

myCancellable = AppState.shared
    .objectWillChange.sink 
       // react here
    

【讨论】:

【参考方案2】:

假设abc 是同一类型(Asperi 向我指出它们不在示例中,因为c 是一个数组),您可以使用Publishers.MergeMany

myCancellable = Publishers.MergeMany([$a,$b,$c]).sink  newValue in 


对于一组参数,此函数还有更具体的版本。例如,在您的情况下,您可以使用 Publishers.Merge3

通常,在我在网上看到的示例中,您会看到Publishers.MergeMany 后跟collect(),它会在继续之前收集所有发布者的结果,将结果作为数组发布。不过,从您的问题来看,这听起来并不能满足您的需求,因为您希望每次单个成员更改时都会收到通知。

【讨论】:

MergeMany 适用于一种类型,但 c 是主题启动问题中的数组,因此无法编译。 啊——好点子。错过了那个细节。编辑帖子以反映这一点。【参考方案3】:

感谢您的精彩回答。我偶然发现的另一个想法是将我的对象存储在 struct 中并观察它。

struct Stuff
  var a: Object?
  var b: Object?
  var c = [Object]()

然后在我的AppState 班级:

class AppState: ObservableObject
  static let shared = AppState()

  @Published var stuff: Stuff!

然后在发布者中:

myCancellable = AppState.shared.$stuff.sink  stuff in
  print(stuff.a)
  print(stuff.b)
  print(stuff.c)

我喜欢这种方法,因为我不想观察AppState 类中可能发生的所有变化(这可能表明我应该将其分解成更小的部分)。到目前为止,这似乎运作良好。

【讨论】:

以上是关于在组合中收到多个 ObservableObject 属性更改的通知的主要内容,如果未能解决你的问题,请参考以下文章

在 ObservableObject 中调用多个函数

Swiftui:子视图没有收到对 observableobject 的更新

如何告诉 SwiftUI 视图绑定到多个嵌套的 ObservableObject

为 ObservableObject ViewModels 编写单元测试并发布结果

SwiftUI 双向绑定到枚举案例中 ObservableObject 中的值

ObservableObject 不更新视图