张黒猫*_*张黒猫 3 swift swiftui combine observedobject
I created a Model like this:
class TestModel: ObservableObject {
@Published var num: Int = 0
}
Run Code Online (Sandbox Code Playgroud)
Model is be used in "Home" view and "Home"s child view "HomeSub"
struct Home: View {
@StateObject var model = TestModel()
var body: some View {
NavigationView(content: {
NavigationLink(destination: HomeSub(model: model)) { Text("\(model.num)") }
})
}
}
Run Code Online (Sandbox Code Playgroud)
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)")
})
}
}
Run Code Online (Sandbox Code Playgroud)
In HomeSub view, what is the difference between 1 and 2? When I run the project, they have exactly the same behavior.
正如您所写, 和 都@StateObject
在@ObservedObject
子视图中执行相同的操作。但是,两者都不正确,因为他们不必要地创建一个新的TestModel
,只是为了扔掉它并用传入的替换它。
子视图的正确写法是:
@ObservedObject var model: TestModel
Run Code Online (Sandbox Code Playgroud)
在这种情况下,不会在子视图中分配初始值model
,这意味着调用者必须提供它。这正是您想要的。真理的来源之一就是model
父母的观点。
此外,状态变量( 和@State
)@StateObject
应该是private
视图,并且应该始终标记为private
。如果你这样做了:
@StateObject private var model = TestModel()
Run Code Online (Sandbox Code Playgroud)
在子视图中,那么您将无法从父视图传递模型,并且您会看到只能@ObservedObject
在这种情况下使用。
经过进一步测试,似乎 Swift/SwiftUITestModel
在编写为 时避免在子视图中创建@ObservedObject var model = TestModel()
,但该语法仍然会误导读者,并且仍然应该编写为,@ObservedObject var model: TestModel
因为这清楚地表明model
正在从某处初始化else(即从父视图)。
归档时间: |
|
查看次数: |
1487 次 |
最近记录: |