我对Xcode和Objective C非常陌生。所以很可能这是一个简单的问题(:
我试图创建一个应用程序,如果按下Caps Lock键,它会执行某些操作。 而且我需要查看即使应用程序未处于焦点时是否按下了Caps Lock。 即使我的应用无法清晰对焦,我也设法检查大写锁定状态。
但我有一个问题,从while循环中退出。 我无法理解为什么我的应用程序无法看到Caps lock键在循环时进入内部时发生了什么。
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
_spam1 = NO;
[NSEvent addGlobalMonitorForEventsMatchingMask:NSFlagsChangedMask handler:^(NSEvent* event){
[NSThread sleepForTimeInterval:1];
if(event.keyCode == 0x39){ //CAPS LOCK key was pressed
if([event modifierFlags] & NSAlphaShiftKeyMask){
_spam1 = YES;
NSLog(@"caps lock is on");
} else {
_spam1 = NO;
NSLog(@"caps lock is off”);
}
//if I comment this part
//I can see if caps lock is on or off just fine
while(_spam1){
NSLog(@"Spam %@" , event);
NSLog(@"Spam %lu" , [event modifierFlags] & NSAlphaShiftKeyMask);
[NSThread sleepForTimeInterval:1];
if([event modifierFlags] & NSAlphaShiftKeyMask){
//_spam1 = YES;
} else {
_spam1 = NO;
NSLog(@“stop while loop”);
break;
}
}
}
}];
}
答案 0 :(得分:1)
使用框架,而不是再次使用:
创建NSView的新子类并覆盖以下方法之一。在“接口”构建器中设置新的子类视图。 (read more in Event handling guide)
所以你的代码应该是这样的:
// multiKey handling
unichar SPACE_CHARACTER = 0x0020;
- (BOOL)performKeyEquivalent:(NSEvent *)theEvent
{
id responder = [[self window] firstResponder];
if (responder != self)
{
return [super performKeyEquivalent:theEvent];
}
NSUInteger numberOfPressedCharacters = [[theEvent charactersIgnoringModifiers] length];
NSEventType eventType = [theEvent type];
if (eventType == NSKeyDown && numberOfPressedCharacters == 1)
{
unichar key = [[theEvent charactersIgnoringModifiers] characterAtIndex:0];
if (key == SPACE_CHARACTER)
{
[self spaceBarPressed];
return YES;
}
}
return NO;
}
或
//单键处理(没有像shift,ctrl ......这样的修饰符)
- (void)keyDown:(NSEvent *)theEvent
{
// code belongs here
}
答案 1 :(得分:0)
也许我错过了一些东西,但为什么你会有while
循环,因为你的代码评论说没有它可以工作?
概述发生的情况如下:
您对addGlobalMonitorForEventsMatchingMask
的呼叫请求系统在每次事件发生时(匹配)调用您传递的阻止。这是异步完成的,为此,您必须绕过事件循环。
标准应用程序模型是事件驱动的,系统设置主事件循环并调用代码来处理各种事件 - 包括对事件监视块的任何所需调用。在您的代码处理它返回的事件之后,事件循环会转移并获取下一个事件,调用代码来处理它等等。
当你的块被调用时,它会传递一个它需要处理的事件的引用。在一次调用中,系统会异步更改不事件 - 系统将事件作为事件循环处理的一部分获取,调用块,直到该调用返回事件循环无法继续。
因此,在你的while
循环发生的所有前导后,对sleepForTimeInterval
的调用会导致你的应用程序在对块的调用中暂停 - 块不会返回,所以它的调用者,事件循环,也不会继续。在唤醒你的循环继续处理完全相同的事件它被调用时传递,你的块然后继续绕其循环无处...
HTH