据我所知,我应该能够使用 EnvironmentObject 从层次结构中的任何 View 观察和访问模型数据。我有一个像这样的 View ,其中显示 LinkListStore 中数组中的列表。当我打开 AddListView 并添加项目时,它会使用添加的项目正确刷新 ListsView。但是,如果我使用PresentationButton来呈现,我必须执行AddListView().environmentObject(listStore),否则在显示AddListView时会崩溃。我的基本假设是否正确(这种行为很可能是一个错误)还是我误解了 EnvironmentObject 的使用?
基本上:@State将变量绑定(bind)到同一 View 中的 View (例如$text到TextField),@ObjectBinding/BindableObject将变量绑定(bind)到其他 View ,EnvironmentObject执行与@ObjectBinding相同的操作,但不传递每次都存储对象。有了这个,我应该能够从多个 View 向数组添加新项目,并且仍然正确刷新 ListView ?否则我不明白 ObjectBinding 和 EnvironmentObject 之间的区别。
struct ListsView : View {
@EnvironmentObject var listStore: LinkListStore
var body: some View {
NavigationView {
List {
NavigationButton(destination: AddListView()) {
HStack {
Image(systemName: "plus.circle.fill")
.imageScale(.large)
Text("New list")
}
}
ForEach(listStore.lists) { list in
HStack {
Image(systemName: "heart.circle.fill")
.imageScale(.large)
.foregroundColor(.yellow)
Text(list.title)
Spacer()
Text("\(list.linkCount)")
}
}
}.listStyle(.grouped)
}
}
}
#if DEBUG
struct ListsView_Previews : PreviewProvider {
static var previews: some View {
ListsView()
.environmentObject(LinkListStore())
}
}
#endif
最佳答案
来自 Apple 文档 EnvironmentObject :
EnvironmentObject A dynamic view property that uses a bindable object supplied by an ancestor view to invalidate the current view whenever the bindable object changes.
它会转换为绑定(bind)影响当前 View 层次结构。我的猜测是,当您通过PresentationButton 呈现一个新 View 时,您正在创建一个新的层次结构,该层次结构并不 Root 于您的 View (即您向其提供对象的 View )。我猜想这里的解决方法是通过实现一个确认 EnvironmentKey
协议(protocol)的结构来将对象添加到“全局”环境中。
关于dataflow - SwiftUI 中的环境对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56508673/