UndoManager with SwiftData Not Registering Single Undo Actions Properly in macOS Sonoma 14.x

I am encountering an issue with the UndoManager functionality in a SwiftUI application that integrates SwiftData for persistence. This issue occurs specifically in macOS 14 (Sonoma) but works as expected on macOS 15 (Sequoia).

The focused test app I have prepared for demonstration allows users to create ParentItem objects, and for each ParentItem, users can add multiple ChildItem objects. The undo functionality (via Cmd+Z) is not working as expected in Sonoma. When I try to undo a ChildItem addition, the UndoManager does not revert just the last ChildItem added, but instead removes all ChildItems that were added in that session.

Expected Behavior

On macOS 14 (Sonoma), I expect the UndoManager to undo only the most recent transaction (in this case, a single ChildItem insert), similar to how it functions on macOS 15 (Sequoia). Each ChildItem insertion should be treated as a separate undoable action.

Current Behavior

In macOS Sonoma, pressing Cmd+Z undoes the entire list of ChildItems added to a ParentItem in the current session, rather than just the most recent ChildItem. This appears to be an issue with undo grouping, but I’ve confirmed that no explicit grouping is being used.

Question

Is this an issue with UndoManager in macOS Sonoma, particularly in how it interacts with SwiftData persistence? What changes should I make to ensure that each ChildItem insert is treated as an individual undo action in macOS Sonoma, just as it works in Sequoia? Any guidance on isolating the issue or recommended workarounds would be appreciated. I would expect that undo actions for each child addition would be treated as separate transactions, not grouped.

Steps Taken to Solve the Problem

  • I attempted to manually save the model context (modelContext.save()) after each ChildItem insert to ensure proper persistence.
  • I also verified that UndoManager was not grouping operations explicitly by calling beginUndoGrouping() or endUndoGrouping() myself.
  • This issue seems to be tied specifically to macOS Sonoma, as it does not occur on macOS Sequoia, where undoing behaves as expected.

Conditions

  • macOS 14 Sonoma: The issue occurs consistently.
  • macOS 15 Sequoia: The issue does not occur.
  • This issue appears to be independent of hardware, as I’ve tested it on multiple machines.

APIs/Features Potentially Involved

  • UndoManager in a SwiftUI application
  • SwiftData for persistence (using modelContext.save())
  • macOS version-specific behavior

Steps to reproduce

  1. Clone test project (https://github.com/Maschina/SwiftDataUndoManagerExample), compile and run
  2. Create a new ParentItem in the app (via plus toolbar button in the sidebar).
  3. Add multiple ChildItems to the ParentItem (via plus toolbar button in the content / middle column of the navigation split view).
  4. Press Cmd+Z to undo the last addition.

This is most likely a bug that has been fixed in macOS Sequoia. SwiftData undo doesn't work quite well with relationships on macOS Sonoma, and the situation is improved in macOS Sequoia.

If you need to support macOS Sonoma, I’d suggest that you file a feedback report against the issue. I am not sure how the team will prioritize the work though, given macOS Sequoia was formally released.

In this concrete case, you might try to insert the new item to the model context before relating it to the parent, as shown below, to see if that changes anything. I can try as well, but will need to set up a macOS Sonoma machine to do so, which will take time.

let newItem = ChildItem(timestamp: Date())
//newItem.parent = selectedParent
//modelContext.insert(newItem)
modelContext.insert(newItem)
newItem.parent = selectedParent
try? modelContext.save()

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

UndoManager with SwiftData Not Registering Single Undo Actions Properly in macOS Sonoma 14.x
 
 
Q