好的,SwiftUI
和 ObservableObject
,在 iOS 13 上。我有 Model
实现了 ObservableObject
:
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")})
}
}
现在,这行得通了。你按下按钮,它就会在“开”和“关”之间切换。 (在 toggle
@Published
之前,它没有。)但是,日志记录没有按预期工作。我在启动时立即收到两个日志:“Model init”和“2 toggle false -> false”。点击按钮,虽然显然改变了 toggle
的值,但不会导致任何一个闭包执行。
当 View 改变您的模型时,我希望有一种方法可以通知更改,以防您需要,例如更新计算值或同步到磁盘或其他东西。也许 sink
是错误的方法?
具有@Published
字段的ObservableObject
如何在其字段更新时得到通知?
最佳答案
sink
返回值的最新文档功能:
///- 返回:一个可取消的实例;当您结束接收值的分配时使用。取消分配结果将取消订阅流。
本质上这意味着 sink 创建了一个 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
添加到您的属性中,如下所示:
public var toggle: Bool = false {
didSet {
print("1 toggle \(self.toggle)")
}
}
关于ios - 如何监听 ObservableObject,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59852106/