ios - 如何监听 ObservableObject

标签 ios swift observable swiftui

好的,SwiftUIObservableObject,在 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/

相关文章:

IOS 导出合规信息已更改

ios - 插入 View Controller 动画时工具栏按钮闪烁(快速淡出)

ios - 以编程方式添加 TextView

swift - AlamoFire(异步)调用中的 UIProgressView 进度更新非常慢

class - SwiftUI @Published 和 @ObservedObject 不会到达 NavigationLink 目的地

ios - Swift - 如何确保标签跟随 slider 的缩略图?

具有不同格式的 Swift UITextView

ios - 滑动删除是删除 tableView 行的唯一方法吗?

rxjs - 从不完整的 observable 中获取最后一个值

error-handling - RxJS 重试然后 catchError 不起作用