StateObject 属性不会更新视图,但 ObservedObject 会

Posted

技术标签:

【中文标题】StateObject 属性不会更新视图,但 ObservedObject 会【英文标题】:StateObject property doesn't update view but ObservedObject does 【发布时间】:2021-01-16 16:38:44 【问题描述】:

我正在使用@EnvironmentObject var modelData : DBViewModel 的另一个视图中将数据保存到 Realm DB 并将它们加载到此视图中

struct SelectedSinsList: View 
@StateObject var modelData = DBViewModel() //@ObservedObject works, as it always recreates the List when I open this view and values are updated
var body: some View 
    NavigationView 
        ScrollView
            VStack(spacing: 15)
                ForEach(modelData.sins)sin in //..........

【问题讨论】:

【参考方案1】:

这种行为表明您的视图使用新数据进行更新的唯一原因是父视图正在重绘,从而触发“无主”观察对象被重建。

State 和 StateObject 比 View 结构体的失效和重绘更持久。要使用它们,您需要通过调用 self.objectWillChange.send() 将 StateObject 中的回调或发布者连接到其 objectWillChange 发布者

但是如果那个 DBViewModel 已经是一个 environmentObject,为什么要重新创建它呢?

【讨论】:

谢谢,我发现我对 EnvironmentObject 的理解有点错误,..现在我正在顶视图中创建 DBViewModel 的实例,同时还将 .environmentObject(modelData) 设置为所有子视图,因此它们具有祖先,然后在其他任何地方(在那些视图中)使用@EnvironmentObject modelData。 是的。 State/StateObject = 在该视图的生命周期中拥有(这就是您在***视图或 App 结构中使用的内容)。您可能还会发现 environmentObject 是传递颜色和尺寸信息的好方法,而不是使用全局常量。即使是 ButtonStyle 或 ViewModifier 也会收到环境。但有一件事......对应用程序的很大一部分使用相同的视图模型是不可取的,因为它变得脆弱且无所不知。您可能仍想创建单独的 ViewModel,但使用 environmentObject 工厂来实例化这些 ViewModel 并将其数据传递给它们。 如果您采用工厂方法,您可以查看我的回答历史记录,了解如何让视图模型触发其 objectWillChange 发布者。

以上是关于StateObject 属性不会更新视图,但 ObservedObject 会的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI onChange(of: ...) 更新 StateObject

SwiftUI之深入解析@StateObject@ObservedObject和@EnvironmentObject的联系和区别

如何防止 SwiftUI 像使用 @StateObject 一样重新初始化我的包装属性?

从子视图设置 StateObject 值会导致 NavigationView 弹出所有视图

如何以 stateobject 作为参数初始化视图?

SwiftUI:@ObservedObject 与 @StateObject 子视图性能?