在我的 ContentView 中,我有一个 FetchRequest<Project>
。我使用 ProjectView
导航到 NavigationLink
。我从 ProjectView
使用另一个 AddItemView
导航到 NavigationLink
。在 AddItemView
中,当我将 Item
添加到 Project
并调用 container.viewContext.save()
时,AddItemView
会自动关闭回 ContentView
。
我的猜测是保存到 CoreData
会更新 FetchRequest<Project>
列表,从而更新视图,但我不确定。
如何将新的 Item
保存到 Project
中的 CoreData
并且只导航回 ProjectView
而不是 ContentView
?
重现:
// Persistence.swift
import CoreData
struct PersistenceController {
static let shared = PersistenceController()
let container: NSPersistentCloudKitContainer
init(inMemory: Bool = false) {
container = NSPersistentCloudKitContainer(name: "CoreDataBug")
if inMemory {
container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
}
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
/*
Typical reasons for an error here include:
* The parent directory does not exist, cannot be created, or disallows writing.
* The persistent store is not accessible, due to permissions or data protection when the device is locked.
* The device is out of space.
* The store could not be migrated to the current model version.
Check the error message to determine what the actual problem was.
*/
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
}
}
// ContentView.swift
import SwiftUI
struct ContentView: View {
@Environment(\.managedObjectContext) var moc
let projects: FetchRequest<Project>
init() {
projects = FetchRequest<Project>(entity: Project.entity(), sortDescriptors: [
NSSortDescriptor(keyPath: \Project.date, ascending: false)
])
}
var body: some View {
NavigationView {
List {
ForEach(projects.wrappedValue) { project in
NavigationLink(destination: ProjectView(project: project)) {
Text(project.title ?? "Title")
}
}
}
.navigationTitle("Projects")
.toolbar {
ToolbarItem(placement: ToolbarItemPlacement.navigationBarTrailing) {
Button {
withAnimation {
let project = Project(context: moc)
let now = Date()
project.date = now
project.title = now.description
try? moc.save()
}
} label: {
Label("Add Project", systemImage: "plus")
}
}
}
}
}
}
// ProjectView.swift
import SwiftUI
struct ProjectView: View {
@ObservedObject var project: Project
var items: [Item] {
project.items?.allObjects as? [Item] ?? []
}
var body: some View {
List {
ForEach(items) { item in
Text(item.name ?? "")
}
}
.toolbar {
ToolbarItem(placement: ToolbarItemPlacement.navigationBarTrailing) {
NavigationLink(destination: AddItemView(project: project)) {
Label("Add Item", systemImage: "plus")
}
}
}
}
}
import SwiftUI
// AddItemView.swift
import SwiftUI
struct AddItemView: View {
@Environment(\.presentationMode) var presentationMode
@Environment(\.managedObjectContext) var moc
let project: Project
@State private var selectedName: String = ""
var body: some View {
TextField("Type name here", text: $selectedName)
.navigationTitle("Add Item")
.navigationBarItems(trailing: Button("Add") {
let ingestion = Item(context: moc)
ingestion.project = project
ingestion.name = selectedName
try? moc.save()
presentationMode.wrappedValue.dismiss()
})
}
}
ProjectView
中再次单击右上角的加号。在 TextField
中输入名称,然后单击右上角的添加。当 AddItemView
被解除时,它可能会回到 ContentView
。如果没有,请向项目添加另一个项目。