[英]SwiftUI EnvironmentObject does not redraw the current view but its parent view
我试图了解@EnvironmentObject
在ObservableObject
中的属性更改时如何影响重绘。
根据 Apple 关于EnvironmentObject的文档,
每当可观察对象发生变化时,环境对象都会使当前视图无效。
如果上述陈述为真,那么当您按下ContentView
中的按钮时,下面的代码不会使ChildView
失效并重新创建。 这应该打印以下输出。
initializing parent
initializing child
// after pressing the button
initializing child
与我的上述假设相反,它实际上打印
initializing parent
initializing child
// after pressing the button
initializing parent
谁能解释为什么会这样? 为什么ParentView
被重新创建,即使ParentView
不依赖于Library
?
class Library: ObservableObject {
@Published var item: Int = 0
}
struct ContentView: View {
@StateObject var library: Library = Library()
var body: some View {
VStack {
ParentView()
.environmentObject(library)
Button {
library.item += 1
} label: {
Text("increment")
}
}
}
}
struct ParentView: View {
init() {
print("initializing parent")
}
var body: some View {
VStack {
Text("Parent view")
ChildView()
}
}
}
struct ChildView: View {
@EnvironmentObject var library: Library
init() {
print("initializing child")
}
var body: some View {
Text("Child view")
}
}
SwiftUI View 可能有点棘手。
每当可观察对象发生变化时,环境对象都会使当前视图无效。
并不意味着对象本身被重新创建。 它只是意味着视图的主体被调用并且视图自身重建。
请记住,结构不是View
本身,它只是一个“描述”。
我添加了一些打印语句以使这一点更清楚:
struct ContentView: View {
@StateObject var library: Library = Library()
init(){
print("initializing content")
}
var body: some View {
VStack {
let _ = print("content body")
ParentView()
.environmentObject(library)
Button {
library.item += 1
} label: {
Text("increment")
}
}
}
}
struct ParentView: View {
init() {
print("initializing parent")
}
var body: some View {
VStack {
let _ = print("parent body")
Text("Parent view")
ChildView()
}
}
}
struct ChildView: View {
@EnvironmentObject var library: Library
init() {
print("initializing child")
}
var body: some View {
let _ = print("child body")
Text("child")
}
}
这最初打印:
initializing content
content body
initializing parent
parent body
initializing child
child body
按下按钮后:
content body
initializing parent
child body
正如您所见,这些View
的主体取决于Library
,它们各自的主体被重新评估。
ParentView
初始化程序运行是因为在您的ContentView
中,您在正文中调用ParentView()
,因此创建了一个“描述”您的 View 的新结构。 ParentView
的视图本身保持不变,因此不会调用其body
var。
这个关于 SwiftUI 视图的WWDC 2021视频将帮助您更好地理解这一点。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.