1

I'd like to understand/replicate the "group by run loop pass/cycle" feature of NSUndoManger:

NSUndoManager can group multiple calls to registerUndo() into a single "undo" operation when invoked multiple times on the same run loop cycle. This is determined by NSUndoManager.groupsByEvent, which is set to true by default.

So something like this:

// User clicks button... (causes a new run loop event)
undoManager.registerUndo(...) // #1
undoManager.registerUndo(...) // #2

...results in one undo group and clicking Edit → Undo reverts both changes at once.

Somehow NSUndoManager can figure out if two calls to registerUndo() are on the same run loop cycle. How does this work?

My use case:

I have code that sends property change notifications after the user interacts with the UI (e.g. clicks a button). There can be one or more events as the result of a user action. I'd like to group those and update the UI only once at the end of the current run loop.

Mark
  • 6,647
  • 1
  • 45
  • 88
  • "By default undo groups are begun automatically at the start of the event loop". `NSUndoManager` calls `beginUndoGrouping` if you didn't. Could you tell a bit more about your use case? What do you mean by "one or more events as the result of a user action"? How do you update the UI, `reloadData`, `setNeedsDisplayInRect`, draw something? – Willeke May 20 '17 at 12:36
  • Thanks for your input. I don't want to get into the specifics about how or why I update the UI. First and foremost I'm curious to understand what's happening behind the scenes. Essentially I want to batch multiple calls to a method within one run loop cycle. Another example would be to debounce the calls and only consider the very last one per run loop cycle (triggered by a single user interaction). – Mark May 20 '17 at 12:47

1 Answers1

1

NSUndoManager normally creates undo groups automatically during the run loop. The first time it is asked to record an undo operation in the run loop, it creates a new group. Then, at the end of the loop, it closes the group.

source: Undo Operations and Groups

NSUndoManager is part of the same framework as NSRunLoop so maybe NSRunLoop signals NSUndoManager to close a group. You don't know and you shouldn't want to know.

Willeke
  • 14,578
  • 4
  • 19
  • 47
  • "Then, at the end of the loop, it closes the group.", but exactly how does it know when the run loop ends? I do want to know, because I'm curious and I might learn something useful along the way. – Mark May 20 '17 at 14:50
  • `-[NSUndoManager endUndoGrouping]` is called in `+[NSUndoManager(NSPrivate) _endTopLevelGroupings]` which is called in `-[NSApplication run]`. – Willeke May 20 '17 at 22:45