Swift – Захват ключа от NSViewController

Я хотел бы захватить ключевые события в своем маленьком приложении.

Что я наделал:

class ViewController : NSViewController { ... override func keyDown(theEvent: NSEvent) { if theEvent.keyCode == 124 { println("abc") } else { println("abcd") } } override var acceptsFirstResponder: Bool { return true } override func becomeFirstResponder() -> Bool { return true } override func resignFirstResponder() -> Bool { return true } ... } 

Что происходит:

При нажатии клавиши звуковой эффект Funk воспроизводится.

Я видел много сообщений о том, как это делегат принадлежит NSView а NSViewController не имеет доступа. Но функция override функции override автоматически завершается в classе типа NSViewController заставляя меня думать, что это неправильно.

Xcode 8.2.1 • Swift 3.0.2

 import Cocoa class ViewController: NSViewController { @IBOutlet var textField: NSTextField! override func viewDidLoad() { super.viewDidLoad() NSEvent.addLocalMonitorForEvents(matching: .flagsChanged) { self.flagsChanged(with: $0) return $0 } NSEvent.addLocalMonitorForEvents(matching: .keyDown) { self.keyDown(with: $0) return $0 } } override func keyDown(with event: NSEvent) { switch event.modifierFlags.intersection(.deviceIndependentFlagsMask) { case [.command] where event.characters == "l", [.command, .shift] where event.characters == "l": print("command-l or command-shift-l") default: break } textField.stringValue = "key = " + (event.charactersIgnoringModifiers ?? "") textField.stringValue += "\ncharacter = " + (event.characters ?? "") } override func flagsChanged(with event: NSEvent) { switch event.modifierFlags.intersection(.deviceIndependentFlagsMask) { case [.shift]: print("shift key is pressed") case [.control]: print("control key is pressed") case [.option] : print("option key is pressed") case [.command]: print("Command key is pressed") case [.control, .shift]: print("control-shift keys are pressed") case [.option, .shift]: print("option-shift keys are pressed") case [.command, .shift]: print("command-shift keys are pressed") case [.control, .option]: print("control-option keys are pressed") case [.control, .command]: print("control-command keys are pressed") case [.option, .command]: print("option-command keys are pressed") case [.shift, .control, .option]: print("shift-control-option keys are pressed") case [.shift, .control, .command]: print("shift-control-command keys are pressed") case [.control, .option, .command]: print("control-option-command keys are pressed") case [.shift, .command, .option]: print("shift-command-option keys are pressed") case [.shift, .control, .option, .command]: print("shift-control-option-command keys are pressed") default: print("no modifier keys are pressed") } } } 

Чтобы избавиться от мурлычащего звука при нажатии клавиш символа, вам нужно подclassифицировать ваше представление, переопределить метод executeKeyEquivalent и вернуть true.

 import Cocoa class View: NSView { override func performKeyEquivalent(with event: NSEvent) -> Bool { return true } } 

Пример проекта

Я пытался найти ответ для быстрого 3, вот что сработало для меня:

Swift 3

 import Cocoa // We subclass an NSView class MainView: NSView { // Allow view to receive keypress (remove the purr sound) override var acceptsFirstResponder : Bool { return true } // Override the NSView keydown func to read keycode of pressed key override func keyDown(with theEvent: NSEvent) { Swift.print(theEvent.keyCode) } } 

Swift4

Просто нашел решение по той же самой проблеме, Swift4. Идея этого: если нажатая клавиша обрабатывалась пользовательской логикой, обработчик должен возвращать нуль, в противном случае (необработанное) событие …

 class MyViewController: NSViewController { override func viewDidLoad() { super.viewDidLoad() // ... NSEvent.addLocalMonitorForEvents(matching: .keyDown) { if self.myKeyDown(with: $0) { return nil } else { return $0 } } } func myKeyDown(with event: NSEvent) -> Bool { // handle keyDown only if current window has focus, ie is keyWindow guard let locWindow = self.view.window, NSApplication.shared.keyWindow === locWindow else { return false } switch Int( event.keyCode) { case kVK_Escape: // do what you want to do at "Escape" return true default: return false } } } 

И здесь мы: нет звука Purr / Funk при нажатии клавиши …

[Обновление] Добавлена ​​проверка keyWindow. Без этого keyDown () запускается, даже если другое представление / окно содержит первый ответчик …

Мне удается заставить его работать из подclassа NSWindowController

 class MyWindowController: NSWindowController { override func keyDown(theEvent: NSEvent) { print("keyCode is \(theEvent.keyCode)") } } 

ОБНОВИТЬ:

 import Cocoa protocol WindowControllerDelegate { func keyDown(aEvent: NSEvent) } class WindowController: NSWindowController { var delegate: WindowControllerDelegate? override func windowDidLoad() { super.windowDidLoad() delegate = window?.contentViewController as! ViewController } override func keyDown(theEvent: NSEvent) { delegate?.keyDown(theEvent) } } 

и ViewController:

 class ViewController: NSViewController, WindowControllerDelegate { @IBOutlet weak var textField: NSTextField! override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. } override var representedObject: AnyObject? { didSet { // Update the view, if already loaded. } } override func keyDown(theEvent: NSEvent) { textField.stringValue = "key = " + (theEvent.charactersIgnoringModifiers ?? "") textField.stringValue += "\ncharacter = " + (theEvent.characters ?? "") textField.stringValue += "\nmodifier = " + theEvent.modifierFlags.rawValue.description } } 
  • Что такое ошибка связи: OS_xpc_error в Xcode 6?
  • Массив кортежей в Свифте
  • Swift Array дополнительно Тип и подписка (бета-версия 3)
  • Автоматическая компоновка: получить высоту UIImageView, чтобы правильно вычислить высоту ячейки
  • Swift 4 JSON Декодируемый простейший способ декодирования изменения типа
  • UIApplication.registerForRemoteNotifications () необходимо вызывать только из основного streamа
  • Как сделать случайное число между диапазоном для arc4random_uniform ()?
  • Назначить xib для UIView в Swift
  • Swift 4 "Этот class не соответствует кодированию ключевого значения"
  • Swift: переместите ярлык UITableViewCell на новый ViewController
  • Получить пользовательскую версию имени classа в swift (в objc NSStringFromClass было хорошо)
  • Давайте будем гением компьютера.