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

Posted

技术标签:

【中文标题】如何告诉 SwiftUI 视图绑定到多个嵌套的 ObservableObject【英文标题】:How to tell SwiftUI views to bind to more than one nested ObservableObject 【发布时间】:2020-02-14 16:24:59 【问题描述】:

我有两个类嵌套在另一个类中,它是 SwiftUI 视图中的一个可观察对象。即使嵌套类中的属性被声明为@Published,它们的值(当它们改变时)也不会在主视图中更新。

这里已经提出了一个类似的问题,我可以使用它来使其适用于两个子类之一,但不能同时适用于两者。

How to tell SwiftUI views to bind to nested ObservableObjects

这是模型:

class Submodel1: ObservableObject 
  @Published var count = 0


class Submodel2: ObservableObject 
  @Published var count = 0


class Model: ObservableObject 
  @Published var submodel1: Submodel1 = Submodel1()
  @Published var submodel2: Submodel2 = Submodel2()

这是主视图:

struct ContentView: View 
  @ObservedObject var model: Model = Model()

  var body: some View 
    VStack 
      Text("Count: \(model.submodel1.count)")
        .onTapGesture 
          self.model.submodel1.count += 1
        
      Text("Count: \(model.submodel2.count)")
        .onTapGesture 
          self.model.submodel2.count += 1
        
    
  

将此添加到模型类(请参阅之前的 *** 问题)适用于更新 submodel1 更改,但不能同时更新:

  var anyCancellable: AnyCancellable? = nil
  init() 
      anyCancellable = submodel1.objectWillChange.sink  (_) in
          self.objectWillChange.send()
      
   

我正在寻找的是将 submodel1 和 submodel2 的更改传递给我的视图的某种方式。

【问题讨论】:

我刚刚发布了一个替代解决方案in this answer。我希望这会有所帮助。 【参考方案1】:

您可以使用CombineLatest 扩展您链接到的问题的答案,让您的模型在任一基础对象发生更改时触发其objectWillChange 发布者:

import Combine

class Model: ObservableObject 
    @Published var submodel1: Submodel1 = Submodel1()
    @Published var submodel2: Submodel2 = Submodel2()

    var anyCancellable: AnyCancellable? = nil

    init() 
        anyCancellable = Publishers.CombineLatest(submodel1.$count,submodel2.$count).sink(receiveValue: _ in
            self.objectWillChange.send()
        )
    

【讨论】:

这是一个很好的解决方案,我在发布者中使用了视图修饰符onReceive 块来更新状态变量,然后在视图主体中使用了使用该状态变量的那个。 combine latest 好像最多有 4 个对象?如果我们有超过 4 个对象怎么办? 我想回答 Marwan 的问题:如果我的对象多于 Publishers.CombineLatest4 可以处理的数量怎么办? developer.apple.com/documentation/combine/publishers/… 现在我对 combine 和 SwiftUI 有了更多经验,我可能不会使用这种方法。我将创建一个ViewModel,它使用Model 来公开和处理对相关属性的更新。视图模型订阅模型中的属性并公开新发布的属性。 只是想花点时间欣赏一下这个答案如何拯救了我的一天。实际上,我的最后三天。这让我发疯,我找不到解决问题的方法。谢谢。

以上是关于如何告诉 SwiftUI 视图绑定到多个嵌套的 ObservableObject的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI如何让绑定到同一个状态的多个TextField呈现出不同输入行为

SwiftUI如何让绑定到同一个状态的多个TextField呈现出不同输入行为

如何在 SwiftUI 的视图控制器中实现数据绑定?

如果操作未立即完成,则 SwiftUI 视图在绑定到 @Published var 时没有动画

如何将 SwiftUI 视图绑定到数组中元素的属性

SwiftUI:如何将 NSManagedObjectContext 传递到多个视图模型中