'Manage Undo across multiple NSTextFields in the same window

While Undo for multiple NSTextViews in a window work persistently, the same is not the case for NSTextField controls by default.

I like to make Undo behave the same for NSTextField as it works with NSTextView.

I have so far found out that NSTextField uses its own private NSUndoManager, which does enable and handle the Undo/Redo menus autmatically, but without using the window's shared undoManager, and without marking the connected document dirty ("edited"): If I provide a private NSUndoManager instance to an NSTextField, it'll behave the same.

So I've tried, by overwriting undoManagerForTextView:, to have the NSTextFields in the window use the window's shared undoManager. That will indeed lead to the effect that the text fields share the same undo stack, and I can still issue an Undo after editing and then leaving a specific text field.

However, the problem is that it'll then crash, because it appears that the Undo gets applied to the wrong (i.e. the currently active) text field and not to the one the undo action was created from.

I've provided a simple example here: https://github.com/tempelmann/Undo_shared_NSTextFields

It's a freshly created document based app, with two text fields and two text views in the main window. To enable the shared undo manager for the text fields, I've created a subclass ("CustomTextField") of NSTextField that overrides the following function to provide the shared undo manager:

-(NSUndoManager *)undoManagerForTextView:(NSTextView *)view { // NSTextViewDelegate
    return view.window.undoManager;
}

And the text fields in the storyboard are set to this subclass instead of NSTextField.

When run, it looks like this:

window with 4 edit controls

Now, if you edit the first and the second text view, and then use Undo twice, it'll undo the changes in each text view just fine.

But if you try the same with the two text fields, e.g. by replacing the longer preset texts in the fields with something shorter (such as "1" and "2"), you'll find that Undo replaces the text in the same active text field twice:

enter image description here

How do I make Undo in the text fields behave correctly, i.e. the same as the text views do?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source