Xcode Objective C while循环无法访问全局变量

时间:2015-10-06 11:16:55

标签: objective-c xcode macos cocoa while-loop

我对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;
                }
            }                            
        }
    }];       
}

2 个答案:

答案 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