SwiftUI @Published 属性正在 DetailView 中更新

Posted

技术标签:

【中文标题】SwiftUI @Published 属性正在 DetailView 中更新【英文标题】:SwiftUI @Published Property Being Updated In DetailView 【发布时间】:2021-01-15 01:33:54 【问题描述】:

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

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

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

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

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

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

【问题讨论】:

不看部分代码就说不准 关键字可能是“链”,你不能有一个 ObservedObject 链,你必须对链中的每个都使用 @ObservedObject 但我们只能在看到代码时具体告诉你。 【参考方案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() 
    
...


【讨论】:

以上是关于SwiftUI @Published 属性正在 DetailView 中更新的主要内容,如果未能解决你的问题,请参考以下文章

来自 @Published 属性的 SwiftUI 动画从视图外部更改

在需要@Binding 的地方传递@Published(SwiftUI、Combine)

Swift Combine - @Published 属性数组

当我通过鼠标单击更改 SwiftUI 列表的选择时,@Published 属性的 didSet 被调用了两次

SwiftUI:属性装饰器的理解@State,@Binding,@ObservedObject,@Published,@Environment,@EnvironmentObject

SwiftUI:属性装饰器的理解@State,@Binding,@ObservedObject,@Published,@Environment,@EnvironmentObject