首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何收听ObservableObject

如何收听ObservableObject
EN

Stack Overflow用户
提问于 2020-01-22 03:16:41
回答 2查看 12.2K关注 0票数 18

好的,那么SwiftUIObservableObject,在iOS 13上,我有实现ObservableObjectModel

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
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“和"2切换假-> false”。点击按钮,虽然显然改变了toggle的值,但并不会导致任何一个闭包的执行。

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

在更新字段时,如何通知具有ObservableObject字段的@Published字段?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-01-22 06:33:35

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,但不会保留它。一旦您的init完成,订阅服务器就会被删除并从内存中删除。您需要通过创建这样一个强大的引用来保持它们:

代码语言:javascript
运行
复制
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,如下所示:

代码语言:javascript
运行
复制
    public var toggle: Bool = false {
        didSet {
            print("1 toggle \(self.toggle)")
        }
    }
票数 23
EN

Stack Overflow用户

发布于 2020-01-22 06:59:44

您的ObservableObject类Model是正确的,但是:

1. ObjectWillChange应该是ObservableObjectPublisher()类型。

,它将objectWillChange属性创建为ObservableObjetPublisher的实例。这来自组合框架,这就是为什么您需要添加导入组合以使代码编译。一个可观察的对象发布者的工作很简单:每当我们想告诉世界我们的对象已经改变了,我们就要求发行者为我们做这件事。

2.您需要观察的属性(Toggle)应该以如下方式实现:

代码语言:javascript
运行
复制
 var toggle = "" {
        willSet {
            objectWillChange.send()
        }
    }

第二,我们在模型的Toggle属性上附加了一个willSet属性观察者,这样我们就可以在值发生变化时运行代码。在我们的示例代码中,每当切换更改时,我们都调用objectWillChange.send(),这就是告诉objectWillChange发布者发布我们的数据已经更改的消息,以便任何订阅的视图都可以刷新。

确保类模型符合@ObservedObject,并且它的实例被标记为 ObservableObject

,因为您的模型类符合ObservableObject,所以您可以像使用任何其他@ObservedObject属性一样使用它。所以,我们可以用它来观看切换,就像这样:

代码语言:javascript
运行
复制
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

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59852106

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档