7

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.

2
  • Where do you want to capture the Key Down event? NSWindow, NSTableView, NSButton? Also, please post what you have tried. Commented Jul 31, 2015 at 15:04
  • @ZoffDino I have deleted what I tried earlier. I believe I want to capture the event at NSView, but i'm not for sure on that. Commented Jul 31, 2015 at 16:08

2 Answers 2

7

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

Sign up to request clarification or add additional context in comments.

5 Comments

Okay I believe I understand how that works. So the delegate methods are going in my 'ViewController' class. So how do those two lines(that would go in 'applicationDidFinishLaunching' change when I put them in a class that already has a view?
the protocol must be added to the class which processes the keystrokes and the set delegate line to the view controller. If the view belongs to a view controller then the class of this view must be changed to MyView. Then you have to reference the view this way: let view = self.view as! MyView
I have tried that and a few other things, still not working. I appreciate your help. By any chance do you have a working version of this code implemented in a view controller?
I edited the post to use a subclass of NSViewController. Consider the added variable acceptsFirstResponder in the NSView subclass
That'll be the winner! It worked. Thanks so much sir!
0
let kLeftArrowKeyCode: UInt16 = 123 let kRightArrowKeyCode: UInt16 = 124 let kDownArrowKeyCode: UInt16 = 125 let kUpArrowKeyCode: UInt16 = 126 override func keyDown(with event: NSEvent) { switch event.keyCode { case kLeftArrowKeyCode: print("left") break case kRightArrowKeyCode: print("right") break case kDownArrowKeyCode: print("down") break case kUpArrowKeyCode: print("up") break default: print("other") super.keyDown(with: event) break } print("Key with number: \(event.keyCode) was pressed") } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.