【问题标题】:What is the difference between @StateObject and @ObservedObject in child views in swiftUIswiftUI中子视图中的@StateObject和@ObservedObject有什么区别
【发布时间】:2020-10-27 09:46:51
【问题描述】:

我创建了一个这样的模型:

class TestModel: ObservableObject {
    @Published var num: Int = 0
}

模型用于“Home”视图和“Home”的子视图“HomeSub”

struct Home: View {
    
    @StateObject var model = TestModel()
    
    var body: some View {
        NavigationView(content: {
            NavigationLink(destination: HomeSub(model: model)) { Text("\(model.num)") }
        })
    }
}
struct HomeSub: View {
   //1
    @StateObject var model = TestModel()
   //2
    @ObservedObject var model = TestModel()

    var body: some View {
        VStack {
            Text("\(model.num)")
                .padding()
                .background(Color.red)
            Button("Add") {
                model.num += 1
            }
        }
        .onChange(of: model.num, perform: { value in
            print("homeSub: \(value)")
        })
        
    }
}

在 HomeSub 视图中,1 和 2 有什么区别? 当我运行项目时,它们的行为完全相同。

【问题讨论】:

    标签: swift swiftui combine observedobject


    【解决方案1】:

    正如您所写,@StateObject@ObservedObject 在子视图中执行相同的操作。但是,两者都不正确,因为他们不必要地创建了一个新的TestModel,只是为了扔掉它并用传入的那个替换它。

    子视图的正确写法是:

    @ObservedObject var model: TestModel
    

    在这种情况下,子视图中的model 没有分配初始值,这意味着调用者必须提供它。这正是你想要的。一个事实来源,即父视图中的model

    此外,状态变量(@State@StateObject)对于视图应该是 private,并且应该始终用 private 标记。如果你这样做了:

    @StateObject private var model = TestModel()
    

    在子视图中,您将无法从父视图传递模型,并且您会看到在这种情况下只能使用 @ObservedObject


    经过进一步测试,Swift/SwiftUI 似乎避免在子视图中创建TestModel,当它写为@ObservedObject var model = TestModel() 时,但该语法仍然会误导读者,它仍然应该写为@987654335 @ 因为这清楚地表明 model 正在从其他地方(即从父视图)初始化。

    【讨论】:

      【解决方案2】:

      它们几乎可以互换使用,并且在您的设置中创建相同模型的 2 个实例。

      @StateObject 的生命周期由 SwiftUI 管理,仅适用于 iOS 14+。

      https://developer.apple.com/documentation/swiftui/stateobject

      @ObservableObject 的生命周期由开发人员管理(有时可以通过 View 刷新无意中重新初始化,因为它应该来自父 View),它在 iOS 13+ 中可用。

      https://developer.apple.com/documentation/swiftui/managing-model-data-in-your-app

      【讨论】:

        【解决方案3】:

        在这种情况下,最好使用@ObservedObject,因为您要从父级注入值。 @StateObject 旨在独立地在 View 上保存一个对象(它的生命周期由 SwiftUI 管理)。由于注入,这里不需要它。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-02-09
          • 2019-10-25
          • 1970-01-01
          • 1970-01-01
          • 2022-07-19
          • 1970-01-01
          相关资源
          最近更新 更多