swiftui - @EnvironmentObject 和 @ObservedObject 有什么区别?
问题描述
我一直在阅读 SwiftUI 中的属性包装器,我发现它们做得很好,但我真正不明白的一件事是@EnvironmentObject和@ObservedObject之间的区别。
从我目前学到的知识来看,当我们在应用程序的各个地方都需要一个对象但我们不需要将它传递给所有这些对象时,我看到使用@EnvironmentObject 。例如,如果我们有层次结构 A -> B -> C -> D 并且对象是在 A 处创建的,它会保存在环境中,以便我们可以将它直接从 A 传递给 D,如果 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对象。不同之处在于 Environment 传递 .environmentObject(order)而 Observed 直接传递EditView(order: order)。对我来说,两者都做同样的工作,只是他们的声明不同,因此我希望得到一些解释或更好的例子。
解决方案
正如您所注意到的,@ObservedObject
需要从一个视图传递到另一个视图。当您没有太多视图时,简单的视图层次结构可能会更好。
假设您具有以下层次结构:
ViewA -> ViewB -> ViewC -> ViewD
现在,如果您希望您的@ObservedObject
from 位于ViewA
其中ViewB
,则直接将其传递给init
.
但是,如果您也想要它ViewD
怎么办?ViewB
如果你在and中不需要它怎么办ViewC
?
使用 an@ObservedObject
您需要手动将其从 传递ViewA
给ViewB
,然后传递给ViewC
,然后传递给ViewD
. 而且您需要在每个子视图中声明它。
使用@EnvironmentObject
它很容易 - 只需将其传递给顶级视图:
ViewA().environmentObject(someObservableObject)
然后你只在使用它的视图中声明它——这可能会使你的代码更具可读性。
笔记
环境中的每个对象(视图层次结构)都可以访问注入的@EnvironmentObject
. 如果您不想要这个(隐私很重要),您可能需要将其作为@ObservedObject
替代传递。
推荐阅读
- java - 有没有办法清除 IntelliJ 输出终端?
- android - android - 按钮使页面背景变为灰色
- python-3.x - python pyautogui 模块不支持孟加拉语文本
- machine-learning - 在分类中手动分类与决策树分类
- java - 是 java.util.Optional
映射函数线程安全?如果是,我该如何测试它? - symfony - 生成文档时 Api 平台重命名类?
- wordpress - 在 WooCommerce 供应商页面中显示 ACF 自定义字段
- javascript - 在登录页面以外的页面上使用 session_start()
- linux - 通过 nohup 检查是否成功启动
- jestjs - 如何从 Jest Test 返回自定义结果