SwiftUI @Published 属性正在 DetailView 中更新

时间:2021-01-15 01:33:54

标签: swiftui

我试图了解我是否遵循 SwiftUI @Published 和 @ObservedObject 的理论。

理论 我有一个从服务器接收更新的模型。模型发布对模型中数据的任何更改。

我的主视图从模型中观察这个列表,并创建一个带有单元格视图的列表视图,该视图推送到详细视图。单元格视图已发布。

详细视图观察单元格视图的变化。

我认为应该发生的事情 当模型更新时,这将更新列表视图,确实如此。 当模型更新时,详细视图会在加载时更新。没有。

如果存在@Published 和@ObservedObject 链,为什么模型更新时详细视图不更新?

1 个答案:

答案 0 :(得分:1)

ObservableObjects 不嵌套。您可以选择手动触发 objectWillChange。这实际上是一件很棒的事情,因为您可以使用 EnvironmentObject 工厂来连接您的应用程序,而无需将任何内容暴露给视图,也不会强制所有内容一次全部更新。

如果你知道它已经从回调中改变了,你可以自己触发它 objectWillChange.send()。

您还可以订阅发布者(例如,另一个 ObservableObjects ObjectWillChangePublisher,或某些网络管道)并在收到值时触发接收者 ObservableObject 的发布者。

这是一个 redux 风格的代码示例,它非常疯狂并与每次更新有关。


import Foundation
import Combine

open class Republisher: ObservableObject {
    public func republish() {
        objectWillChange.send()
    }

    public init () {}
}

class VM: ObservableObject {
    private var republishers = Set<AnyCancellable>()

    internal var root: RootStore

    init(_ root: RootStore, _ repubs: Republisher...) {
        self.root = root

        root.objectWillChange
            .receive(on: DispatchQueue.main)
            .sink(receiveValue: { [weak self] _ in
                guard let self = self else { return }
                self.objectWillChange.send()
            })
            .store(in: &republishers)

        repubs.forEach { repubs in
            repubs.objectWillChange
                .receive(on: DispatchQueue.main)
                .sink(receiveValue: { [weak self] _ in
                    guard let self = self else { return }
                    self.objectWillChange.send()
                })
                .store(in: &republishers)
        }
    }

    deinit { republishers = [] }
}

import Foundation
import Combine

public final class RootStore: Republisher {
    private var middlewareCancellables: Set<AnyCancellable> = []

    public init(state: RootState,
                reducer: @escaping Reducer<RootState, RootAction>,
                middleware: Middlewares = []) {
        self.state = state
        self.reducer = reducer
        self.middleware = RootStore.mandatoryWares(and: middleware)
    }

    public private(set) var state: RootState {
        didSet { republish() }
    }
...
}