How to handle arrow key event in Cocoa app?
Asked Answered
R

2

14

How to handle arrow key event in Cocoa app?

Repeater answered 14/5, 2011 at 6:8 Comment(0)
R
12

See this code. I assumed the class is subclass of NSView.

#pragma mark    -   NSResponder

- (void)keyDown:(NSEvent *)theEvent
{
    NSString*   const   character   =   [theEvent charactersIgnoringModifiers];
    unichar     const   code        =   [character characterAtIndex:0];
        
    switch (code) 
    {
        case NSUpArrowFunctionKey:
        {
            break;
        }
        case NSDownArrowFunctionKey:
        {
            break;
        }
        case NSLeftArrowFunctionKey:
        {
            [self navigateToPreviousImage];
            break;
        }
        case NSRightArrowFunctionKey:
        {
            [self navigateToNextImage];
            break;
        }
    }
}

A view should be a first responder to receive events. Maybe this code will be required to support that.

#pragma mark    -   NSResponder
- (BOOL)canBecomeKeyView
{
    return  YES;
}
- (BOOL)acceptsFirstResponder
{
    return  YES;
}

To use this method, the class should be subclass of NSResponder. See the other answer handling without subclassing NSResponder.

Repeater answered 14/5, 2011 at 6:8 Comment(8)
You also need to be a responder and be in the responder chain. Being a view that accepts first responder is a good way to fulfill this prerequisite.Surrounding
The key codes have been the same since the days of yore and aren't likely to change. See this informative article by Peter Hosey. The fact that they're only visible to us in a Carbon header doesn't mean much. CGEvents use them primarily, not the corresponding unicode.Polyglot
@Josh OK. I understood. But I couldn't find defined key code constant values. To use it reliably, some kind of specification is required. Can I know where the official specification is?Repeater
@Eonil: please understand that I wasn't saying there was anything wrong at all with your method. I just wanted to present a different one.Polyglot
@Josh Oh, of course I do. I didn't know the method so I'm appreciating to you about it :) I just want to make it clear the 'key-code' stuff. If you felt some uncomfortable, sorry for my poor English :(Repeater
@Eonil: No, no fault of your English. I was just worried that my written words may have sounded like criticism, and I wanted to make clear that this was not my intent. :) I'm glad to be able to share this information! I wish I knew more, or understood it better, so I could really explain it correctly.Polyglot
@Eonil: Just stumbled across a fairly recent Cocoa-dev thread which talks about the deprecation/non-deprecation of various parts of Carbon. It cleared a few things up for me; thought you might be interested. Summary is: GUI Carbon stuff is out, most everything else is still okay, documentation should reflect this but doesn't do such a good job.Polyglot
@Josh It looks fine to use Carbon features absent on Cocoa :)Repeater
T
3

In my case I wanted a presented NSViewController subclass to be able to listen to arrow key events for navigation with minimal effort. Here's the best solution I've found, a slight variation of Josh Caswell's answer.

Define an event monitor (optional), can be locally in your NSViewController subclass .m

id keyMonitor;

Then start monitoring events, for example in viewDidLoad.

keyMonitor = [NSEvent addLocalMonitorForEventsMatchingMask:NSKeyDownMask handler:^(NSEvent *event) {

    unichar character = [[event characters] characterAtIndex:0];
    switch (character) {
        case NSUpArrowFunctionKey:
            NSLog(@"Up");
            break;
        case NSDownArrowFunctionKey:
            NSLog(@"Down");
            break;
        case NSLeftArrowFunctionKey:
            NSLog(@"Left");
            break;
        case NSRightArrowFunctionKey:
            NSLog(@"Right");
            break;
        default:
            break;
    }
    return event;
}];

To remove the monitor when not required (assuming you defined it)

[NSEvent removeMonitor:keyMonitor];
Toxoplasmosis answered 10/12, 2015 at 22:26 Comment(1)
This is a very useful API for some edge cases where the responder chain doesn't do what you want.Plummy

© 2022 - 2024 — McMap. All rights reserved.