如何在SwiftUI中创建对象的实例而不重复?

时间:2019-07-03 07:29:35

标签: ios swift swiftui

这是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)")
    }
}

所以问题很复杂。

  1. ObjectsListView在计算MyObject(store: myObjectsStore)时在初始化时创建body的实例。
  2. MyObject对象将在初始化时设置其store属性,因为它应该知道它属于myObjectsStore还是anotherMyObjectsStore
  3. 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 对象?

UPD: 这是project,代表与对象重复有关的错误。 我仍然不知道为什么在这种情况下对象会重复。但是至少我知道原因。原因是这一行:

@Environment(\.myObjectsStore.objects) var myObjectsStores: Places

我尝试与该包装器共享我的模型,以使其在每个单个视图(包括模态视图)中可用,而没有将它们作为arg传递给新视图初始化器,而其他方式则无法使用,例如{ 1}}包装器。出于某种原因,@EnvironmentObject包装器会重复。

因此,我将所有变量从@Environment(\.keyPath)替换为Environment(\.),现在一切正常。

1 个答案:

答案 0 :(得分:0)

我已经找到解决方法。

Here's表示与对象重复有关的错误的项目存储库以及修复该错误的版本。我仍然不知道在这种情况下如何复制对象。但是我想出了原因。发生的原因是此行:

@Environment(\.myObjectsStore.objects) var myObjectsStores: MyObjectsStore

我已经使用@Environment(\.key)将模型连接到导航堆栈中的每个视图,包括Modal,而SwiftUI中提供的其他方法无法使用该视图,例如:@State@ObjectBinding@EnvironmentObject。由于某种原因,@Environment(\.key)包装器会产生这些重复。

因此,我将所有变量从@Environment(\.)替换为@ObjectBinding,现在几乎一切正常。

注意:该代码在销售代表中仍然通过每个工作流程演练创建一个其他对象。因此,它完全创建了两个对象,而不是一个。可以通过this answer中提供的方式来解决此问题。