Search code examples
swiftkeydown

I need to get arrow key presses, but keyDown won't call (Swift)


I am trying to build a Mac App which displays images and I want to move on to the next image when I press the right arrow key. I have looked all over stackoverflow and the internet, but just can't seem to get it.

What I tried... I tried to use keyDown(theEvent: NSEvent)but it does not call when I press any keys. I believe this is because it is not in a text field of some kind, but not sure.

What Happens... When i'm testing the program, I press a key (with keyDown function ready to println("Key Pressed")) and I get the OS X reject noise and no println to the console.

I have heard of some people subclassing NSView to override acceptsFirstResponder, but I am new to subclassing so any direction you could point me in would be great. Or if there is a way to do it w/o subclassing NSView that would be great!

Thanks in advance! Sorry for the noobness.


Solution

  • Subclassing is less difficult than it seems.

    Short tutorial:

    General assumption: keystrokes are going to be received in the view of a NSViewController subclass and to be processed in the view controller class

    • Create a new Cocoa Class named MyView as a subclass of NSView
    • Replace the contents of the created class with

      import Cocoa
      
      let leftArrowKey = 123
      let rightArrowKey = 124
      
      protocol MyViewDelegate {
        func didPressLeftArrowKey()
        func didPressRightArrowKey()
      }
      
      class MyView: NSView {
      
         var delegate : MyViewDelegate?
      
         override func keyDown(event: NSEvent) {
           let character = Int(event.keyCode)
           switch character {
           case leftArrowKey, rightArrowKey:
             break
           default:
             super.keyDown(event)
           }
         }
      
         override func keyUp(event: NSEvent) {
           let character = Int(event.keyCode)
           switch character {
           case leftArrowKey:
             delegate?.didPressLeftArrowKey()
           case rightArrowKey:
             delegate?.didPressRightArrowKey()
           default:
             super.keyUp(event)
           }
         }
      
          override var acceptsFirstResponder : Bool {
            return true
          }
        } 
      
      • Change the class of the view of the ViewController in Interface Builder to MyView
      • In the ViewController class add the protocol MyViewDelegate- for example

        class ViewController: NSViewController, MyViewDelegate {
        
      • In viewDidLoad() add

        let view = self.view as! MyView
        view.delegate = self
        self.nextResponder = view
        
      • Implement the following delegate methods and add your code to switch the image(s)

        func didPressLeftArrowKey() {
          println("didPressLeftArrowKey")
          // process keystroke left arrow
        }
        
        func didPressRightArrowKey() {
          println("didPressRightArrowKey")
          // process keystroke right arrow
        }
        

    The delegate methods are called when the appropriate arrow keys are released