我正在尝试使用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
方法的“-”按钮应删除当前选择的模型对象,并返回到默认的空细节视图。不幸的是,我正在努力提出正确的方法来做到这一点。我相信我需要进行以下互动:
remove
方法将删除当前选定的对象PresentationMode.dismiss()
第3步是我正在努力的一步。到目前为止,在不使用Core Data类之上的视图模型类的情况下,一切工作都可以进行,但是我感到很困惑,试图弄清楚如何获取子视图来调用dismiss()
。这需要从详细信息视图中进行,因为它从环境中获取了PresentationMode
,并且NavigationView
对其进行了更改。
虽然我可以通过Binding
来获得模型的isDeleted
属性的@ObservedObject
,但我不知道该如何实际应对; Binding
似乎在幕后使用发布者,但是例如,它们没有公开我可以与onPublish
联系的发布者。
在isDeleted
上进行KVO可能是可行的,但是从值类型上监听并不是很好;这里没有删除观察者的好地方,如果应用运行时间过长,可能会出现问题。
这种类型的问题有什么指导?
答案 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()
}
}
}
}