如何在不重复的情况下在 SwiftUI 中创建对象的实例?
How to create an instance of an object in SwiftUI without duplication?
这是 问题的下一部分。
我有以下代码。
应用程序的初始视图:
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
是 @BindableObject,因为它们的更改由 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
我尝试与此包装器共享我的模型,以使其在每个视图(包括模态视图)中可用,而无需将它们作为参数传递给新视图初始化程序,其他方式不可用,例如@EnvironmentObject
包装器。出于某种原因 @Environment(\.keyPath)
包装器会产生重复。
所以我只需将所有变量从 Environment(\.)
替换为 ObjectBinding
,现在一切正常。
我找到了解决方法。
Here's 表示对象重复错误的项目回购以及修复此问题的版本。我仍然不知道在那种情况下对象是如何复制的。但我想通了为什么。发生这种情况是因为这一行:
@Environment(\.myObjectsStore.objects) var myObjectsStores: MyObjectsStore
我已经使用 @Environment(\.key)
将我的模型连接到导航堆栈中的每个视图,包括 Modal
一个,SwiftUI 中提供的其他方式不可用,例如:@State
, @ObjectBinding
, @EnvironmentObject
。并且出于某种原因 @Environment(\.key)
包装器产生了这些重复项。
所以我只需将所有变量从 @Environment(\.)
替换为 @ObjectBinding
,现在几乎一切正常。
注意:代表中的代码仍然通过每个工作流程演练创建一个额外的对象。所以它完全创建了两个对象而不是一个。此行为可以通过 this answer.
中提供的方式修复
这是
我有以下代码。
应用程序的初始视图:
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
是 @BindableObject,因为它们的更改由 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
我尝试与此包装器共享我的模型,以使其在每个视图(包括模态视图)中可用,而无需将它们作为参数传递给新视图初始化程序,其他方式不可用,例如@EnvironmentObject
包装器。出于某种原因 @Environment(\.keyPath)
包装器会产生重复。
所以我只需将所有变量从 Environment(\.)
替换为 ObjectBinding
,现在一切正常。
我找到了解决方法。
Here's 表示对象重复错误的项目回购以及修复此问题的版本。我仍然不知道在那种情况下对象是如何复制的。但我想通了为什么。发生这种情况是因为这一行:
@Environment(\.myObjectsStore.objects) var myObjectsStores: MyObjectsStore
我已经使用 @Environment(\.key)
将我的模型连接到导航堆栈中的每个视图,包括 Modal
一个,SwiftUI 中提供的其他方式不可用,例如:@State
, @ObjectBinding
, @EnvironmentObject
。并且出于某种原因 @Environment(\.key)
包装器产生了这些重复项。
所以我只需将所有变量从 @Environment(\.)
替换为 @ObjectBinding
,现在几乎一切正常。
注意:代表中的代码仍然通过每个工作流程演练创建一个额外的对象。所以它完全创建了两个对象而不是一个。此行为可以通过 this answer.
中提供的方式修复