好的,所以在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
?
答案 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