Upvote:3

struct ItemEditorConfig: Identifiable {
    let id = UUID()
    let context: NSManagedObjectContext
    let item: Item
    
    init(viewContext: NSManagedObjectContext, objectID: NSManagedObjectID) {
        // create the scratch pad context
        context = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
        context.parent = viewContext
        // load the item into the scratch pad
        item = context.object(with: objectID) as! Item
    }
}

struct ItemEditor: View {
    @ObservedObject var item: Item // this is the scratch pad item
    @Environment(\.managedObjectContext) private var context
    @Environment(\.dismiss) private var dismiss // causes body to run
    let onSave: () -> Void
    @State var errorMessage: String?
    
    var body: some View {
        NavigationView {
            Form {
                Text(item.timestamp!, formatter: itemFormatter)
                if let errorMessage = errorMessage {
                    Text(errorMessage)
                }
                Button("Update Time") {
                    item.timestamp = Date()
                }
            }
            .toolbar {
                ToolbarItem(placement: .navigationBarLeading) {
                    Button("Cancel") {
                        dismiss()
                    }
                }
                ToolbarItem(placement: .navigationBarTrailing) {
                    Button("Save") {
                        // first save the scratch pad context then call the handler which will save the view context.
                        do {
                            try context.save()
                            errorMessage = nil
                            onSave()
                        } catch {
                            let nsError = error as NSError
                            errorMessage  = "Unresolved error \(nsError), \(nsError.userInfo)"
                        }
                    }
                }
            }
        }
    }
}

struct EditItemButton: View {
    let itemObjectID: NSManagedObjectID
    @Environment(\.managedObjectContext) private var viewContext
    @State var itemEditorConfig: ItemEditorConfig?
    
    var body: some View {
        Button(action: edit) {
            Text("Edit")
        }
        .sheet(item: $itemEditorConfig, onDismiss: didDismiss) { config in
            ItemEditor(item: config.item) {
                do {
                    try viewContext.save()
                } catch {
                    // 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.
                    let nsError = error as NSError
                    fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
                }
                itemEditorConfig = nil // dismiss the sheet
            }
            .environment(\.managedObjectContext, config.context)
        }
    }
    
    func edit() {
        itemEditorConfig = ItemEditorConfig(viewContext: viewContext, objectID: itemObjectID)
    }
    
    func didDismiss() {
        // Handle the dismissing action.
    }
}

struct DetailView: View {
    @ObservedObject var item: Item
    
    var body: some View {
        Text("Item at \(item.timestamp!, formatter: itemFormatter)")
            .toolbar {
                ToolbarItem(placement: .navigationBarTrailing) {
                    EditItemButton(itemObjectID: item.objectID)
                }
            }
    }
}

More Answer related to the Same Query

Upvote:2

struct ItemEditor: View {
    @Environment(\.dismiss) private var dismiss
    @Environment(\.managedObjectContext) private var context
    
    @ObservedObject var item: Item
    var body: some View {
        NavigationView {
            Form {
                TextField("Name", text: Binding($item.name)!)
            }
            .navigationTitle("New Item")
            .toolbar {
                Button("Save") {
                    try? context.save()
                    dismiss()
                }
            }
        }
    }
}

Credit Goes to: stackoverflow.com

Related question with same questions but different answers