【问题标题】:Dismiss navigation view when Core Data object is deleted删除核心数据对象时关闭导航视图
【发布时间】:2020-02-17 02:08:08
【问题描述】:

我正在尝试使用 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())

DetailRow 是一个NavigationLink,它还定义了详细视图:

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

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

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

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

第 3 步是我正在努力解决的问题。到目前为止,一切都很好,没有在核心数据类之上使用视图模型类,但我觉得试图弄清楚如何让子视图调用dismiss()。这需要从详细视图中进行,因为它从环境中获取 PresentationMode,而 NavigationView 会更改它。

虽然我可以通过@ObservedObject 获得模型的isDeleted 属性的Binding,但我不知道我该如何应对这种变化; Binding 似乎在幕后使用了发布者,但他们并没有公开我可以与 onPublish 联系的发布者。

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

这类问题的指导是什么?

【问题讨论】:

  • 你发现了吗?我也有同样的问题。

标签: swift macos core-data swiftui


【解决方案1】:

这是我的解决方案。

这是我的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()
            }
        }
    }
}

【讨论】:

    猜你喜欢
    • 2012-09-26
    • 2023-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-27
    • 2012-06-17
    • 2016-11-07
    相关资源
    最近更新 更多