我正在实现一种脚本语言,用户可能会意外地导致无限循环。我想让用户有机会通过按住命令键并键入句点(“.”)键来取消这种失控循环。
目前,我使用以下代码检查每行一次是否取消:
NSEvent * evt = [[NSApplication sharedApplication] nextEventMatchingMask: NSKeyDownMask untilDate: [NSDate date] inMode: WILDScriptExecutionEventLoopMode dequeue: YES];
if( evt )
{
NSString * theKeys = [evt charactersIgnoringModifiers];
if( (evt.modifierFlags & NSCommandKeyMask) && theKeys.length > 0 && [theKeys characterAtIndex: 0] == '.' )
{
// +++ cancel script execution here.
}
}
这样做的问题是,它会吃掉用户在脚本运行时可能键入的任何键盘事件,即使脚本应该能够检查按键。此外,它不会使相应的 NSKeyUp 事件出队。但是,如果我告诉它也将 key up 事件出队,它可能会将在我的脚本启动之前举行的按键的 keyUp 出队,并且我的应用程序可能永远不会发现按键已释放。
另外,我不想让任何事件出队,直到我知道它实际上是一个取消事件,但是没有单独的出队调用,并且仅仅假设第二个调用中最前面的事件将是同一个事件感觉不可靠。即使它保证是第一个,也意味着用户输入“a”,然后输入 Cmd-。意味着我只能看到“a”而看不到Cmd-。如果我不使事件出队,则在它后面。
还有比使用旧的 Carbon 备用 GetKeys() 更好的选择吗?幸运的是,这似乎可以在 64 位中使用。
另外,我正在考虑添加一个 NSStatusItem,它会添加一个按钮来取消脚本到菜单栏等位置。但是我将如何以不让用户(例如)的方式处理事件?当脚本希望成为主线程的统治者时选择菜单?
有什么建议吗?有推荐吗?
最佳答案
按照 Dave 的建议,使用 -addLocalMonitorForEventsMatchingMask:
可能是实现此目的的最简单方法,是的。
我只是想补充一点,尽管你感觉不可靠,但事件队列确实是一个队列,事件不会改变顺序。调用 -nextEventMatchingMask:inMode:dequeue:NO 、检查事件、确定它是您要处理的事件,然后调用 -nextEventMatchingMask:inMode:dequeue:NO 是完全安全的(也是事件循环中的标准做法) >-nextEventMatchingMask:inMode:dequeue:YES
以便使用它。只需确保两次调用之间的掩码和模式相同即可。
关于cocoa - 如何在紧密循环中检查命令周期?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16132003/