I did a post a while back about how to enable undo functionality when using CoreData. It continues to work great for AppKit or UIKit apps, but what about if you’ve adopted SwiftUI as Apple is suggesting we do?
Well… unfortunately the previous approach won’t work quite as well.
After a few hours working this, it turns out it’s quite simple… You have two options:
1. Using the @Environment property:
First, be sure you pass the right managedObjectContext to your top level view as part of the @main App:
var body: some Scene {
WindowGroup {
someTopLevelView
.environment(\.managedObjectContext,container.viewContext)
}
Then, in the SwiftUI file where you want to add undo functionality you’ll add the following @Environment properties
//CoreData convinience
@Environment(\.managedObjectContext) private var viewContext
@Environment(\.undoManager) private var undoManager
And then you’ll connect them, ensuring the SwiftUI undoManager is connected to the one you’ve created:
someView
.onAppear{
viewContext.undoManager = undoManager
}
Voila!
2. Alternatively you can implement your own Undo/Redo Commands in SwiftUI:
.commands {
CommandGroup(replacing: .undoRedo) {
Button(“Undo”) {
//Trigger your own undo with your created undoManager
undoManager?.undo()
}
.keyboardShortcut(KeyEquivalent(“z”), modifiers: [.command])
.disabled(undoManager?.canUndo == false)
Button(“Redo”) {
//Trigger your own undo with your created undoManager
undoManager?.redo()
}
.keyboardShortcut(KeyEquivalent(“z”), modifiers: [.command, .shift])
.disabled(undoManager?.canRedo == false)
}
}
And that’s it, now you have full undo functionality for Core Data in SwiftUI.
Questions / comments? I’m at @MarcMasVi
Marc