SwiftUI - 通过嵌套引用类型传播更改通知

Ant*_*ton 5 propagation swiftui combine observableobject

我想将 SwiftUI 中的 ObservableObject 行为扩展到嵌套类,我正在寻找正确的方法来做到这一点。它可以使用Combine“手动”完成,但我想使用SwiftUI有一种更简洁的方法,我希望你能指出我正确的方向。这就是我的意思……

下面是 ObservableObject 的一个典型应用,它使 View 动态响应引用类型的变化。点击按钮切换showText值,使文本在屏幕上出现/消失:

import SwiftUI

class MyClass: ObservableObject {
    @Published var showText = false
}


struct ContentView: View {

    @ObservedObject var instance = MyClass()

    var body: some View {
        VStack(spacing: 10) {
            Button(action: {
                print(self.instance.showText)
                self.instance.showText.toggle()
            }) {
                Text("BUTTON").bold().padding()
                    .foregroundColor(.white)
                    .background(Color.red)
            }
            if instance.showText {
                Text("Hello, World!")
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这工作正常。

但是下面的修改呢,其中包含的类showText是 an InnerClass,它本身包含在 an 中OuterClass?按钮切换showText得很好,但值更改的通知不再通过OuterClass实例传播到视图,因此视图根本不再显示文本。

import SwiftUI

class OuterClass: ObservableObject {
    @Published var innerInstance = InnerClass()
}

class InnerClass: ObservableObject {
    @Published var showText = false
}

struct ContentView: View {

    @ObservedObject var outerInstance = OuterClass()

    var body: some View {
        VStack(spacing: 10) {
            Button(action: {
                self.outerInstance.innerInstance.showText.toggle()
            }) {
                Text("BUTTON").bold().padding()
                    .foregroundColor(.white)
                    .background(Color.red)
            }
            if outerInstance.innerInstance.showText {
                Text("Hello, World!")
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

什么是优雅的解决方法?

nin*_*nes 3

明确致电发布者,您将收到通知:

struct ContentView: View {   
  @ObservedObject var outerInstance = OuterClass()
  var body: some View {
    VStack(spacing: 10) {
      Button(action: {
        self.outerInstance.innerInstance.showText.toggle()
        // Call the publisher
        self.outerInstance.objectWillChange.send()
      }) {
        Text("BUTTON").bold().padding()
          .foregroundColor(.white)
          .background(Color.red)
      }
      if outerInstance.innerInstance.showText {
        Text("Hello, World!")
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)