Swift - Capture keydown from NSViewController

匿名 (未验证) 提交于 2019-12-03 01:39:01

问题:

I would like to capture keyevents in my little app.

What I have done:

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     }  ... } 

What happens:

When a key pressed, the Funk sound effect plays.

I've seen many posts talking about how this is a delegate the belongs to NSView and NSViewController does not have access. But the keydown function override auto completes in a class of type NSViewController leading me to believe that this is wrong.

回答1:

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")         }     } } 

To get rid of the purr sound when pressing the character keys you need to subclass your view, override the method performKeyEquivalent and return true.

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

Sample Project



回答2:

I was trying to find an answer for swift 3, here is what worked for me:

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 func draw(_ dirtyRect: NSRect) {      super.draw(dirtyRect) }  // Override the NSView keydown func to read keycode of pressed key override func keyDown(with theEvent: NSEvent)      {      Swift.print(theEvent.keyCode)     return      }  } 


回答3:

I manage to get it work from subclass of NSWindowController

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

UPDATE:

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)     }  } 

and 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     }  } 


回答4:

Swift4

Just found a solution for the very same problem, Swift4. The idea behind that: if the pressed key was handled by a custom logic, the handler shall return nil, otherwise the (unhandled) event...

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 {       switch Int( event.keyCode) {       case kVK_Escape:          // do what you want to do at "Escape"          return true       default:           return false       }    } } 

And here we are: no Purr / Funk sound when key is pressed...



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!