Ios 如何聆听可观察对象

Ios 如何聆听可观察对象,ios,swift,observable,swiftui,Ios,Swift,Observable,Swiftui,好的,iOS 13上的SwiftUI和ObservableObject。我有一个实现ObservieObject的模型: class Model: ObservableObject { @Published public var toggle: Bool = false init() { NSLog("Model init") objectWillChange.sink { void in NSLog("1 toggle

好的,iOS 13上的SwiftUI和ObservableObject。我有一个实现ObservieObject的模型:

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)")
        }
    }
}
和一个切换
切换
的按钮:

struct ContentView: View {
    @ObservedObject var model: Model

    var body: some View {
        Button(action: {
            self.model.toggle.toggle()
        }, label: {Text(model.toggle ? "on" : "off")})
    }
}
现在,这是可行的。你按下按钮,它会在“开”和“关”之间切换。(在进行
切换之前,
@Published
,它没有执行此操作。)但是,日志记录无法按预期工作。我在启动时立即得到两个日志:“modelinit”和“2 toggle false->false”。点击按钮,虽然显然改变了
切换的值
,但不会导致任何一个闭包执行

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


具有
@已发布的
字段的
可观察对象如何在其字段更新时得到通知?

函数返回值的最新文档:

//-返回:一个可取消的实例;结束对接收值的赋值时使用。取消分配结果将中断订阅流。

本质上,这意味着sink创建了一个
订户,但不保留它。一旦初始化完成,订阅服务器就会被删除并从内存中删除。您需要通过创建如下强引用来保持它们:

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

我没有使用过很多<代码>合并,但我经常看到的一个选择,就是把一个<代码> DIDSET 添加到你的属性中,如:

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

您的ObservieObject类模型已正确完成,但:

1。ObjectWillChange的类型应为ObservableObjectPublisher()

创建objectWillChange属性作为的实例 ObservieObjetPublisher。这来自于Combine框架,该框架 这就是为什么需要添加import Combine来编译代码。这个 可观察对象发布者的工作很简单:只要我们愿意 告诉全世界我们的目标已经改变,我们要求出版商去做 这是给我们的

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

 var toggle = "" {
        willSet {
            objectWillChange.send()
        }
    }
第二,我们将一个willSet属性观察器附加到切换 属性,以便我们可以随时运行代码 价值变化。在您的示例代码中,我们调用objectWillChange.send() 无论何时切换更改,这都会告诉objectWillChange 发布者发布我们的数据已更改的消息,以便 订阅的视图可以刷新

3。确保您的类模型符合ObserveObject,并且its实例标记为@ObserveObject

由于您的模型类符合ObserveObject,您可以 使用它就像使用任何其他@ObservedObject属性一样。所以,我们可以使用 观看切换时会像这样,如下所示:

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)")
        }
    }
}
希望这有帮助, 参考:

啊,这就是我所缺少的!谢谢有时我可能会使用
didSet
,但知道如何使用objectWillChange同时监视所有内容也很好
objectDidChange
可能也很不错,但我认为至少在默认情况下,我们并没有这样做。