How to handle arrow key event in Cocoa app?
Asked
Active
Viewed 1.1k times
2 Answers
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.

eonil
- 83,476
- 81
- 317
- 516
-
1You 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. – Peter Hosey May 14 '11 at 09:36
-
The key codes have been the same since the days of yore and aren't likely to change. See [this informative article](http://boredzo.org/blog/archives/2007-05-22/virtual-key-codes) 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. – jscs May 16 '11 at 03:53
-
@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? – eonil May 16 '11 at 05:13
-
@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. – jscs May 16 '11 at 05:41
-
@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 :( – eonil May 16 '11 at 06:12
-
@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. – jscs May 16 '11 at 06:19
-
1@Eonil: Just stumbled across [a fairly recent Cocoa-dev thread](http://www.cocoabuilder.com/archive/cocoa/281840-high-level-toolkit-is-it-obsolete-or-not.html) 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. – jscs Jun 25 '11 at 21:44
-
@Josh It looks fine to use Carbon features absent on Cocoa :) – eonil Jun 26 '11 at 07:04
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];

Daniel Nordh
- 600
- 6
- 9
-
This is a very useful API for some edge cases where the responder chain doesn't do what you want. – w0mbat Jun 25 '20 at 03:33