如何听一个ObservableObject

时间:2020-01-22 03:16:41

标签: ios swift observable swiftui

好的,所以在iOS 13上是SwiftUI和ObservableObject。我有实现ObservableObject的模型:

const animals = [
  "Cows", "Pigs", "Sheep", "Goats", "Lambs", "Rabbits"
]

const _updateLocationData = (value) => { 
    var tempLocations = [];
    locations.forEach(function(res) {
        if (animals.includes(value) && res[value] === "Yes") {
            tempLocations.push(res);
        }
    });
}

和一个切换class Model: ObservableObject { @Published public var toggle: Bool = false init() { NSLog("Model init") objectWillChange.sink { void in NSLog("1 toggle \(self.toggle)") } $toggle.sink { v in NSLog("2 toggle \(self.toggle) -> \(v)") } } } 的按钮:

toggle

现在,这可行。您按下按钮,它会在“打开”和“关闭”之间切换。 (在制作struct ContentView: View { @ObservedObject var model: Model var body: some View { Button(action: { self.model.toggle.toggle() }, label: {Text(model.toggle ? "on" : "off")}) } } toggle之前,它没有这样做。)但是,日志记录无法按预期工作。我在启动时立即得到两个日志:“ Model init”和“ 2 toggle false-> false”。轻按按钮,尽管显然改变了@Published的值,但不会导致两个闭包都执行。

当视图改变您的模型时,我希望有一种方法可以通知您更改,以防您需要例如更新计算值或同步到磁盘或其他内容。也许toggle是错误的方法?

如何更新具有sink个字段的ObservableObject

2 个答案:

答案 0 :(得分:8)

有关sink函数上的返回值的最新文档:

/// - Returns: A cancellable instance; used when you end assignment of the received value. Deallocation of the result will tear down the subscription stream.

从本质上讲,这意味着接收器生成Subscriber但不保留它。初始化完成后,订阅者将被删除并从内存中删除。您需要通过创建这样的强大参考文献来保持它们的存在:

class Model: ObservableObject {
    @Published public var toggle: Bool = false

    var changeSink: AnyCancellable?
    var toggleSink: AnyCancellable?

    init() {
        NSLog("Model init")
        changeSink = objectWillChange.sink { void in
            NSLog("1 toggle \(self.toggle)")
        }
        toggleSink = $toggle.sink { v in
            NSLog("2 toggle \(self.toggle) -> \(v)")
        }
    }
}

我并没有使用太多Combine,但是我经常看到的一种可能会考虑的替代方法是,像这样向属性添加didSet

    @Published public var toggle: Bool = false {
        didSet {
            print("1 toggle \(self.toggle)")
        }
    }

答案 1 :(得分:3)

您的ObservableObject类模型正确完成,但是:

1。 ObjectWillChange的类型应为ObservableObjectPublisher()

这将创建一个objectWillChange属性作为以下对象的实例 ObservableObjetPublisher。这来自合并框架 这就是为什么需要添加import Combine来编译代码的原因。的 可观察对象发布者的工作很简单:只要我们愿意 告诉世界我们的对象已经改变,我们要求发布者 对我们来说。

2。您需要观察(切换)的属性应通过以下方式实现:

 var toggle = "" {
        willSet {
            objectWillChange.send()
        }
    }

第二,我们在Toggle上附加了willSet属性观察器 Model的属性,以便我们可以在任何时候运行代码 价值变化。在您的示例代码中,我们调用objectWillChange.send() 每当切换更改时,这就是告诉objectWillChange的原因 发布者发布有关我们的数据已更改的消息,以便任何 订阅的视图可以刷新。

3。确保您的类Model符合ObservableObject,并且其实例标记为 @ObservedObject

由于您的Model类符合ObservableObject,因此您可以 就像使用其他@ObservedObject属性一样使用它。因此,我们可能会使用 像这样观看切换,就像这样:

struct ContentView: View {
    @ObservedObject var model: Model

    var body: some View {
        Button(action: {
            self.model.toggle.toggle()
        }, label: {Text($model.toggle ? "on" : "off")})
    }
}

希望这会有所帮助, 参考: https://www.hackingwithswift.com/quick-start/swiftui/how-to-send-state-updates-manually-using-objectwillchange