删除核心数据对象后关闭导航视图

时间:2019-10-21 01:03:25

标签: swift macos core-data swiftui

我正在尝试使用SwiftUI和CoreData来构建macOS应用程序。该应用程序的主窗口有一个NavigationView,列表项绑定到获取请求,选择这些项中的任何一个都会填充详细信息视图。导航视图如下所示:

NavigationView {
    VStack(spacing: 0) {
        List(fetchRequest) { DetailRow(model: $0) }
            .listStyle(SidebarListStyle())

        HStack {
            Button(action: add) { Text("+") }
            Button(action: remove) { Text("-") }
        }
    }

    Text("Select a model object")
}.navigationViewStyle(DoubleColumnNavigationViewStyle())

DetailRowNavigationLink,它也定义了详细视图:

NavigationLink(destination: ModelDetail(model: model)) {
    Text(model.name)
}

我相信ModelDetail的内容不是很重要;无论哪种方式,我都相当灵活。

在导航视图中,调用remove方法的“-”按钮应删除当前选择的模型对象,并返回到默认的空细节视图。不幸的是,我正在努力提出正确的方法来做到这一点。我相信我需要进行以下互动:

  1. 子视图与导航视图通信,当前选择了哪个模型对象
  2. 用户单击“-”按钮,导航视图的remove方法将删除当前选定的对象
  3. 子视图注意到其模型对象已删除
  4. →子视图调用PresentationMode.dismiss()

第3步是我正在努力的一步。到目前为止,在不使用Core Data类之上的视图模型类的情况下,一切工作都可以进行,但是我感到很困惑,试图弄清楚如何获取子视图来调用dismiss()。这需要从详细信息视图中进行,因为它从环境中获取了PresentationMode,并且NavigationView对其进行了更改。

虽然我可以通过Binding来获得模型的isDeleted属性的@ObservedObject,但我不知道该如何实际应对; Binding似乎在幕后使用发布者,但是例如,它们没有公开我可以与onPublish联系的发布者。

isDeleted上进行KVO可能是可行的,但是从值类型上监听并不是很好;这里没有删除观察者的好地方,如果应用运行时间过长,可能会出现问题。

这种类型的问题有什么指导?

1 个答案:

答案 0 :(得分:0)

这里是我的解决方法。

这是我的NoteDetailView。它允许从该视图或“导航”层次结构中的“主”视图中删除。此解决方案适用于Mac,iPad和iPhone。

我向实体添加了一个可选的dateDeleted。删除记录后,我只需向该属性添加Date()的值并保存上下文。在我的FetchRequests中,我仅断言dateDeleted = nil。稍后我将在我的应用程序中添加一个垃圾桶和东西,以便人们可以查看或永久清空其垃圾。

然后,我使用状态变量和通知来清除我的视图。您可以更改所需功能的代码:

struct NoteDetailView: View {
    var note: Note
    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
    @Environment(\.managedObjectContext) var managedObjectContext
    @State var noteBody: String = ""
    @State var showEditNoteView: Bool = false
    @State var showEmptyView: Bool = false

    init(note: Note) {
        self.note = note
        self._noteBody = State(initialValue: note.body)
    }

    var body: some View {
        VStack {
            if (!showEmptyView) {
                Text("NOT DELETED")
            }
            else {
                EmptyView()
            }
        }
        .navigationBarTitle(!showEmptyView ? note.title : "")
        .navigationBarItems(trailing:
            HStack {
                if (!showEmptyView) {
                    Button(action: {
                        self.showEditNoteView.toggle()
                    }, label: {
                        NavBarImage(image: "pencil")
                    })
                    .sheet(isPresented: $showEditNoteView, content: {
                        EditNoteView(note: self.note).environment(\.managedObjectContext, self.managedObjectContext)
                    })
                }
            }
        )
        .onReceive(NotificationCenter.default.publisher(for: .NSManagedObjectContextDidSave)) { _ in
            if (self.note.dateDeleted != nil) {
                self.showEmptyView = true
                self.presentationMode.wrappedValue.dismiss()
            }
        }
    }
}
相关问题