6

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

下面是一个典型的 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!")
            }
        }
    }
}

这工作正常。

但是下面的修改呢,其中包含的类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!")
            }
        }
    }
}

对此有什么优雅的解决方法?

4

2 回答 2

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!")
      }
    }
  }
}
于 2020-02-08T01:38:43.200 回答
3

它可以在你的模型中完成

import Combine // required for AnyCancelable

class OuterClass: ObservableObject {
    private let _inner: InnerClass
    var innerInstance: InnerClass {
        return _inner
    }
    var store = Set<AnyCancellable>()
    init(_ inner: InnerClass) {
        _inner = inner
        inner.$showText.sink { [weak self] _ in
            self?.objectWillChange.send()
        }.store(in: &store)
    }
}

以及如何在您的示例中使用

import SwiftUI
import Combine

class OuterClass: ObservableObject {
    private let _inner: InnerClass
    var innerInstance: InnerClass {
        return _inner
    }
    var store = Set<AnyCancellable>()
    init(_ inner: InnerClass) {
        _inner = inner
        inner.$showText.sink { [weak self] _ in
            self?.objectWillChange.send()
        }.store(in: &store)
    }
}

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

let inner = InnerClass()
let outer = OuterClass(inner)

struct ContentView: View {

    @ObservedObject var outerInstance = outer

    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!")
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

如果你想观察你内在对象的任何变化,那就去做吧!

class OuterClass: ObservableObject {
    private let _inner: InnerClass
    var innerInstance: InnerClass {
        return _inner
    }
    var store = Set<AnyCancellable>()
    init(_ inner: InnerClass) {
        _inner = inner
        inner.objectWillChange.sink { [weak self] _ in
            self?.objectWillChange.send()
        }.store(in: &store)
    }
}

更新:基于下面的讨论

class OuterClass: Combine.ObservableObject {
    private let _inner: InnerClass
    var innerInstance: InnerClass {
        return _inner
    }
    var store = Set<AnyCancellable>()
    init(_ inner: InnerClass) {
        _inner = inner
        inner.objectWillChange.sink { [weak self] _ in
            self?.objectWillChange.send()
        }.store(in: &store)
    }
}
于 2020-02-08T12:52:00.957 回答