我一直在阅读有关SwiftUI中的属性包装器的信息,我发现它们做得很好,但是我真正不了解的一件事是 @EnvironmentObject 和 @ObservedObject 。
到目前为止,我了解到,当我们在应用程序的各个位置都需要一个对象时,便会使用 @EnvironmentObject ,但我们不需要将其传递给所有对象他们。例如,如果我们具有层次结构A-> B-> C-> D,并且该对象是在A处创建的,则将其保存在环境中,以便在D需要时将其直接从A传递到D。
如果我们使用在A处创建并需要传递给D的 @ObservedObject ,那么我们也需要遍历B和C。
但是我仍然不知道如何决定使用哪个。 这是我制作的2个示例项目:
struct ContentView2: View {
var order = Order2()
var body: some View {
VStack {
EditView2()
DisplayView2()
}
.environmentObject(order)
}
}
struct EditView2: View {
@EnvironmentObject var user: Order2
var body: some View {
HStack{
TextField("Fruit", text: $user.item)
}
}
}
struct DisplayView2: View {
@EnvironmentObject var user: Order2
var body: some View {
VStack{
Text(user.item)
}
}
}
class Order2: ObservableObject {
@Published var item = "Orange"
}
和
struct ContentView: View {
var order = Order()
var body: some View {
VStack {
EditView(order: order)
DisplayView(order: order)
}
}
}
struct EditView: View {
@ObservedObject var order: Order
var body: some View {
HStack{
TextField("Fruit", text: $order.item)
}
}
}
struct DisplayView: View {
@ObservedObject var order: Order
var body: some View {
VStack{
Text(order.item)
}
}
}
class Order: ObservableObject {
@Published var item = "Apple"
}
两个代码都对视图进行相同的更新。同样,两个ContentView都传递一个 Order 对象。区别在于环境通过 .environmentObject(order),而观察到的则直接通过 EditView(order:order)传递。对我来说,两者都做同样的工作,只是他们的声明是不同的,因此,请您提供一些解释或更好的示例。
答案 0 :(得分:2)
您已经注意到,@ObservedObject
需要从一个视图传递到另一个视图。没有太多视图时,对于简单的视图层次结构可能会更好。
假设您具有以下层次结构:
ViewA -> ViewB -> ViewC -> ViewD
现在,如果您希望将@ObservedObject
中的ViewA
放入ViewB
中,则直接将其传递到init
中就没问题了。
但是如果您也想在ViewD
中使用它怎么办?如果您在ViewB
和ViewC
中不需要它,该怎么办?
使用@ObservedObject
时,您需要将其从ViewA
手动传递到ViewB
,然后传递到ViewC
,再传递到{{1} }。并且您需要在每个子视图中声明它。
使用ViewD
很简单-只需将其传递到顶级视图即可:
@EnvironmentObject
然后,您仅在使用它的视图中声明它-这可能会使您的代码更具可读性。
注意
环境(视图层次结构)中的 每个对象都可以访问注入的ViewA().environmentObject(someObservableObject)
。如果您不希望这样做(隐私很重要),则可能需要将其作为@EnvironmentObject
传递。