I have been stuck on this for a while. There are similar problems on stack overflow but none have led me to the solution I'm looking for. Also, can't seem to find any info in the official docs.
I am building a macOS application programatically. I have set up my own menu bar programmatically. I have an NSTextView
and some NSTextfield
s which I have set up perfectly fine as subviews of another view. Everything working except the undo/redo functionality, which I have read is supported in these classes. I have myTextView.allowsUndo = true
but it just does not work. Why is the undo manager not automatically doing stuff like I'm pretty sure it is supposed to?
Here is the relevant part of my menu code:
let editMenu = NSMenuItem()
editMenu.submenu = NSMenu(title: "Edit")
editMenu.submenu?.items = [
NSMenuItem(title: "Undo", action: #selector(UndoManager.undo), keyEquivalent: "z"),
NSMenuItem(title: "Redo", action: #selector(UndoManager.redo), keyEquivalent: "Z")
]
I'm thinking it might be something to do with linking the UndoManager to my window or the textfields and views? I want to set this up without having to make my own undo manager functions.
This works on my system:
// **** Edit Menu **** //
let editMenu = NSMenuItem()
editMenu.submenu = NSMenu(title: "Edit")
editMenu.submenu?.addItem(withTitle: "Undo", action: Selector(("undo:")), keyEquivalent: "z")
editMenu.submenu?.addItem(withTitle: "Redo", action: Selector(("redo:")), keyEquivalent: "Z")
editMenu.submenu?.addItem(.separator())
editMenu.submenu?.addItem(withTitle: "Cut", action: #selector(NSText.cut(_:)), keyEquivalent: "x")
editMenu.submenu?.addItem(withTitle: "Copy", action: #selector(NSText.copy(_:)), keyEquivalent: "c")
editMenu.submenu?.addItem(withTitle: "Paste", action: #selector(NSText.paste(_:)), keyEquivalent: "v")
editMenu.submenu?.addItem(withTitle: "Select All", action: #selector(NSText.selectAll(_:)), keyEquivalent: "a")
Make sure you have the other edit menu items. In order to 'undo' something you have to 'do' it to start with. Also need to set txtView.allowsUndo = true as you have correctly done. Please note that Selector(someString) is different from #selector(). It's actually old swift syntax, but it still works. Swift relies on objc for selectors.