(Примечание к решению)
Как обрабатывать событие со стрелкой в Cocoa приложении?
(Примечание к решению)
Как обрабатывать событие со стрелкой в Cocoa приложении?
Смотрите этот код. Я предположил, что класс является подклассом 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;
}
}
}
Представление должно быть первым ответчиком для получения событий. Возможно, этот код будет необходим для поддержки этого.
#pragma mark - NSResponder
- (BOOL)canBecomeKeyView
{
return YES;
}
- (BOOL)acceptsFirstResponder
{
return YES;
}
Чтобы использовать этот метод, класс должен быть подклассом NSResponder
. См. Другую обработку ответов без подкласса NSResponder.
Но, но... но я не хочу быть подклассом NSResponder
.
@interface AMonitorNotAResponder : NSObject
@end
@implementation AMonitorNotAResponder
{
id eventMonitor; // An event monitor object; instance of
// private class _NSLocalEventObserver
}
- (id)init
{
self = [super init];
if( !self ) return nil;
NSEvent * (^monitorHandler)(NSEvent *);
monitorHandler = ^NSEvent * (NSEvent * theEvent){
switch ([theEvent keyCode]) {
case 123: // Left arrow
NSLog(@"Left behind.");
break;
case 124: // Right arrow
NSLog(@"Right as always!");
break;
case 125: // Down arrow
NSLog(@"Downward is Heavenward");
break;
case 126: // Up arrow
NSLog(@"Up, up, and away!");
break;
default:
break;
}
// Return the event, a new event, or, to stop
// the event from being dispatched, nil
return theEvent;
};
// Creates an object we do not own, but must keep track
// of so that it can be "removed" when we're done
eventMonitor = [NSEvent addLocalMonitorForEventsMatchingMask:NSKeyDownMask
handler:monitorHandler];
return self;
}
- (void)dealloc
{
[NSEvent removeMonitor:eventMon];
}
@end
Руководство по обработке событий дает некоторые возможные варианты использования. Кажется, это дружественная Cocoa версия CGEventTap
или способ обойти цепочку респондентов для определенной цели. Там ограниченный выбор типов событий, которые можно контролировать, например, только клавиши вниз, а не вверх. В docs есть список.
Также доступно: проверять события, поступающие в любое другое приложение (без возможности их изменения) с помощью addGlobalMonitorForEventsMatchingMask:handler:
. Подобно событиям, этот метод требует включения доступности.
В моем случае я хотел, чтобы представленный подкласс NSViewController мог прослушивать события со стрелкой для навигации с минимальными усилиями. Здесь лучшее решение, которое я нашел, небольшое изменение ответа Джоша Казуэлла.
Определить монитор событий (необязательно), может быть локально в подклассе NSViewController.m
id keyMonitor;
Затем запустите мониторинг событий, например, в 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;
}];
Чтобы удалить монитор, если это не требуется (если вы его определили)
[NSEvent removeMonitor:keyMonitor];