【发布时间】:2019-11-13 20:17:30
【问题描述】:
这是that问题的下一部分。
我有以下代码。
应用的初始视图:
struct InitialView : View {
var body: some View {
Group {
PresentationButton(destination: ObjectsListView()) {
Text("Show ListView")
}
PresentationButton(destination: AnotherObjectsListView()) {
Text("Show AnotherListView")
}
}
}
}
对象的列表视图:
struct ObjectsListView : View {
@Environment(\.myObjectsStore.objects) var myObjectsStores: Places
var body: some View {
Group {
Section {
ForEach(myObjectsStore.objects) { object in
NavigationLink(destination: ObjectDetailView(object: object)) {
ObjectCell(object: object)
}
}
}
Section {
// this little boi
PresentationButton(destination: ObjectDetailView(objectToEdit: MyObject(store: myObjectsStore))) {
Text("Add New Object")
}
}
}
}
}
详细视图:
struct ObjectsDetailView : View {
@Binding var myObject: MyObject
var body: some View {
Text("\(myObject.title)")
}
}
所以问题很复杂。
-
ObjectsListView在计算body时在自身初始化时创建MyObject(store: myObjectsStore)的实例。 -
MyObject对象在其自身初始化时设置其store属性,因为它应该知道它是属于myObjectsStore还是属于anotherMyObjectsStore。 -
myObjectsStore是 @BindableObjects,因为它们的更改由 SwiftUI 本身管理。
所以这种行为最终导致我出乎意料的MyObject() 初始化,因为视图正在计算自己。喜欢:
- 首先
MyObject在ObjectsListView初始化时创建。 - 第二个
MyObject在其PresentationButton按下时创建(预期的)。 - 第三个(有时甚至第四个)
MyObject在关闭ObjectsDetailView时创建。
所以我不知道我应该使用什么模式来只创建一个对象?
我唯一要做的就是制作以下代码:
struct ObjectsListView : View {
@Environment(\.myObjectsStore.objects) var myObjectsStores: Places
@State var buttonPressed = false
var body: some View {
Group {
if buttonPressed {
ObjectDetailView(objectToEdit: MyObject(store: myObjectsStore))
} else {
Section {
ForEach(myObjectsStore.objects) { object in
NavigationLink(destination: ObjectDetailView(object: object)) {
ObjectCell(object: object)
}
}
}
Section {
Button(action: {
self.buttonPressed.toggle()
}) {
Text("Add New Object")
}
}
}
}
}
}
这只是有条件地重绘ObjectsListView 到详细视图。但这完全不符合 iOS 准则。那么如何在 SwiftUI 中为另一个视图创建 Only One 对象呢?
统一更新: 这是project,它代表对象重复的错误。 我仍然不知道为什么在这种情况下对象会重复。但至少我还知道原因。原因是这一行:
@Environment(\.myObjectsStore.objects) var myObjectsStores: Places
我尝试与此包装器共享我的模型,以使其在每个视图(包括模态视图)中都可用,而无需将它们作为 arg 传递给新的视图初始化程序,其他方式不可用,例如 @987654344 @包装。出于某种原因,@Environment(\.keyPath) wrapper 进行了重复。
所以我只需将所有变量从Environment(\.) 替换为ObjectBinding,现在一切正常。
【问题讨论】:
-
我刚刚用虚拟对象测试了这个,我看到了一个初始化,它是在计算视图主体的时候。当
PresentationButton被点击或视图被关闭时,我没有看到另一个初始化。您确定该对象已多次初始化吗?你怎么知道(在对象的init中打印语句?)?额外的对象是与您要创建的对象重复还是不同? -
@RPatel99 感谢您,我找到了解决方案。感谢您的支持!我会用示例项目更新问题,其中第一次提交代表重复错误,第二次显示修复。