"The Selector Keyword Has Been Deprecated in Future Versions of Swift" How to Create Keyboard Shortcuts in Dialog Without an Edit Menu

The Selector keyword has been deprecated in future versions of Swift How can I create Keyboard Shortcuts in Dialog without an Edit Menu

Attempt #2 doesn't work because NSUndoManager has a method with the selector undo and not undo:.

I suggest you create a protocol to represent "an entity that responds to the undo action" and use that protocol to hold your selector:

@objc protocol UndoActionRespondable {
func undo(sender: AnyObject)
}

let undoSelector = #selector(UndoActionRespondable.undo(_:))

Cocoa Keyboard Shortcuts in Dialog without an Edit Menu

What worked for me was using The View Solution presented in Copy and Paste Keyboard Shortcuts at CocoaRocket.

Basically, this means subclassing NSTextField and overriding performKeyEquivalent:.

Update: The CocoaRocket site is apparently gone. Here's the Internet Archive link: http://web.archive.org/web/20100126000339/http://www.cocoarocket.com/articles/copypaste.html

Edit: The Swift code looks like this

class Editing: NSTextField {

private let commandKey = NSEventModifierFlags.CommandKeyMask.rawValue
private let commandShiftKey = NSEventModifierFlags.CommandKeyMask.rawValue | NSEventModifierFlags.ShiftKeyMask.rawValue
override func performKeyEquivalent(event: NSEvent) -> Bool {
if event.type == NSEventType.KeyDown {
if (event.modifierFlags.rawValue & NSEventModifierFlags.DeviceIndependentModifierFlagsMask.rawValue) == commandKey {
switch event.charactersIgnoringModifiers! {
case "x":
if NSApp.sendAction(Selector("cut:"), to:nil, from:self) { return true }
case "c":
if NSApp.sendAction(Selector("copy:"), to:nil, from:self) { return true }
case "v":
if NSApp.sendAction(Selector("paste:"), to:nil, from:self) { return true }
case "z":
if NSApp.sendAction(Selector("undo:"), to:nil, from:self) { return true }
case "a":
if NSApp.sendAction(Selector("selectAll:"), to:nil, from:self) { return true }
default:
break
}
}
else if (event.modifierFlags.rawValue & NSEventModifierFlags.DeviceIndependentModifierFlagsMask.rawValue) == commandShiftKey {
if event.charactersIgnoringModifiers == "Z" {
if NSApp.sendAction(Selector("redo:"), to:nil, from:self) { return true }
}
}
}
return super.performKeyEquivalent(event)
}
}

Edit: The Swift 3 code looks like this

class Editing: NSTextView {

private let commandKey = NSEventModifierFlags.command.rawValue
private let commandShiftKey = NSEventModifierFlags.command.rawValue | NSEventModifierFlags.shift.rawValue

override func performKeyEquivalent(with event: NSEvent) -> Bool {
if event.type == NSEventType.keyDown {
if (event.modifierFlags.rawValue & NSEventModifierFlags.deviceIndependentFlagsMask.rawValue) == commandKey {
switch event.charactersIgnoringModifiers! {
case "x":
if NSApp.sendAction(#selector(NSText.cut(_:)), to:nil, from:self) { return true }
case "c":
if NSApp.sendAction(#selector(NSText.copy(_:)), to:nil, from:self) { return true }
case "v":
if NSApp.sendAction(#selector(NSText.paste(_:)), to:nil, from:self) { return true }
case "z":
if NSApp.sendAction(Selector(("undo:")), to:nil, from:self) { return true }
case "a":
if NSApp.sendAction(#selector(NSResponder.selectAll(_:)), to:nil, from:self) { return true }
default:
break
}
}
else if (event.modifierFlags.rawValue & NSEventModifierFlags.deviceIndependentFlagsMask.rawValue) == commandShiftKey {
if event.charactersIgnoringModifiers == "Z" {
if NSApp.sendAction(Selector(("redo:")), to:nil, from:self) { return true }
}
}
}
return super.performKeyEquivalent(with: event)
}
}

How to add undo/redo support for NSTextView and NSTextField when building a macOS application programmatically?

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.



Related Topics



Leave a reply



Submit