3

NSResponder 定义了许多与键盘操作相关的操作moveUp:,例如moveUpAndModifySelection:moveToBeginningOfLine:。除了按修饰键(例如moveUp:只是Up箭头键)未触发的操作外,我无法在我的 custom 上调用任何操作NSView

这是设置:

  • Xcode 5.1 / 10.9
  • 基本的 Cocoa 应用程序,仅Custom View添加到主窗口。
  • 这个自定义视图只是一个NSViewSTView
  • STView无非是覆盖acceptsFirstResponder返回YES

在此设置中,我的STView实例将正确接收所有键盘事件(包括具有修饰符的事件Ctl-AperformKeyEquivalent:keyDown:预期的那样。(这两种方法都已在下面的讨论中注释掉。)

如果我提供了一个实现,那么当用户按下箭头键时会正确调用thenmoveUp:中定义的。NSRespondermoveUp:Up

令人困惑的moveUp:是,只要Up使用修饰键按下箭头键,也会调用它。当按住修饰键时(例如:)Ctl-Up,我希望调用适当的键盘操作方法。

前任:

  • Ctl-Up-> moveUp:(预期scrollPageUp::)
  • Alt-Up-> moveUp:(预期moveToBeginningOfParagraph::)
  • Shift-Up-> moveUp:(预期moveUpAndModifySelection::)
  • Command-Up-> moveUp:(预期moveToBeginningOfDocument::)

对于所有键/修饰符组合,此模式会重复。

Apple 文档中的两个方面似乎相关:

通读该文档,系统似乎负责将关键事件映射到相应的关键操作。事实上,当没有按下修饰键时,这对我有用。但是当按下修饰键时,事件就像任何其他事件一样被处理并通过正常的响应者链传递。

(我可以看到修饰键事件通过NSApplication sendEvent,尽管NSApplication sendAction:to:from:从未被调用,并继续沿视图层次结构向下移动,鉴于我阅读了上面的文档,我希望这一点。

文档提示文本编辑视图可能会被区别对待。这些键盘操作是否仅发送到编辑文本的视图?如果没有,那么当用户按下时,如何moveUpAndModifySelection:在他们的自定义类上得到一条消息?NSViewShift-Up

作为参考,我将此图表用于键盘绑定,但坦率地说,我已经尝试了几乎所有组合,无论是否列出:

归根结底,我可能只是重写keyDown:并手动处理我感兴趣的所有组合,但我希望至少能理解为什么这对我来说不起作用。

(请注意,此处的预期应用程序是允许用户导航项目的类似网格的视图,很像集合视图。)

任何提示、建议或意见将不胜感激。

更新:

如果您在您的keyDown

- (void)keyDown:(NSEvent *)theEvent {
  ...
  [self interpretKeyEvents:[NSArray arrayWithObject:theEvent]];
}

然后将在您的自定义视图上调用“正确”操作。我认为这是因为我感兴趣的动作是类似文本的动作,它需要输入管理器解释并转换为适当的动作。

我仍然不完全清楚为什么moveUp:正确地被调用。响应者链中的谁在识别Up被按下的箭头键然后发送moveUp:消息?

4

2 回答 2

4

这是对您的自我回答的一种答复,这更像是问题的延伸。

是的,在大多数情况下,有必要调用-[NSResponder interpretKeyEvents:]-[NSTextInputContext handleEvent:]获取键绑定系统来向您发送绑定的操作方法。

至于你为什么得到-moveUp:,我在一个简单的自定义视图类中实现了以下内容:

- (BOOL) acceptsFirstResponder
{
    return YES;
}

- (void) moveUp:(id)sender
{
    NSLog(@"%@", [NSThread callStackSymbols]);
}

这记录了以下调用堆栈:

0   TestKeyUp                           0x000000010000182d -[KeyView moveUp:] + 48
1   AppKit                              0x00007fff85e44012 -[NSWindow _processKeyboardUIKey:] + 325
2   AppKit                              0x00007fff85ab1075 -[NSWindow keyDown:] + 94
3   AppKit                              0x00007fff8589e206 forwardMethod + 104
4   AppKit                              0x00007fff8589e206 forwardMethod + 104
5   AppKit                              0x00007fff8596c0c7 -[NSWindow sendEvent:] + 8769
6   AppKit                              0x00007fff858a0afa -[NSApplication sendEvent:] + 4719
7   AppKit                              0x00007fff858376de -[NSApplication run] + 474
8   AppKit                              0x00007fff858303b0 NSApplicationMain + 364
9   TestKeyUp                           0x000000010000176d main + 33
10  TestKeyUp                           0x0000000100001744 start + 52
11  ???                                 0x0000000000000001 0x0 + 1

NSWindow将向上箭头键作为“键盘界面控制”的一部分处理。这部分记录在案,但并未明确说明它将调用诸如-moveUp:. 显然,这就是它的实现方式。

于 2014-03-29T03:59:48.217 回答
2

通读该文档,系统似乎负责将关键事件映射到相应的关键操作。

没有“系统”。NSResponder 的工作方式如下:将任意消息(只是一串字符)放到响应者链的开头(无论是键盘焦点)。通常它什么都不做,并将它传递给“下一个”响应者。它沿着响应者链无所事事,直到经过 50 或 60 次 null 操作后,最终会说“是的,我会回应!” 它做了一些事情。一旦发生这种情况,响应者链上的任何其他事情都不会知道事件发生了。

通常一个响应者会触发另一个响应者。因此,例如,如果您发送一条keyDown:消息,因为Cmd-S它一直没有执行任何操作,直到最终到达“另存为”菜单项,然后该菜单项saveDocument:位于响应者链的开头,整个过程又重新开始直到它到达 NSDocument,它将执行保存操作。

令人困惑的moveUp:是,只要Up使用修饰键按下箭头键,也会调用它。当按住修饰键时(例如:)Ctl-Up,我希望调用适当的键盘操作方法。

前任:

  • Ctl-Up-> moveUp:(预期scrollPageUp::)
  • Alt-Up-> moveUp:(预期moveToBeginningOfParagraph::)
  • Shift-Up-> moveUp:(预期moveUpAndModifySelection::)
  • Command-Up-> moveUp:(预期moveToBeginningOfDocument::)

这并不令人困惑,响应者链对滚动视图或文本视图一无所知,或者根本不知道任何事情。它只知道应用程序将一条消息keyDownmouseDown:消息推送到链上,并且一毫秒后一条scrollPageUp:消息进入了链,或者它可能没有。响应者链中有很多东西永远不会被使用。如果您需要它们,它们可以被触发,并且有些东西会被 AppKit 触发,但很多不是。

请注意,其中的方法列表NSResponder主要是为了使具有代码自动完成功能的开发人员的生活更轻松,并在使用 GUI 构建界面时填充可用操作列表。您可以将任何 @selector()放在响应者链上(只要它有一个sender参数)。并非所有正在使用的都记录在案。

归根结底,我可能只是重写 keyDown: 并手动处理我感兴趣的所有组合,但我希望至少能理解为什么这对我来说不起作用。

是的。如果可能的话,你应该keyDown:只做类似的事情[self moveUpAndModifySelection:self];。所以基本上是一个没有太多逻辑的大 switch 语句或 if 语句。

反正我就是这样做的:https ://github.com/abhibeckert/Dux/blob/master/Dux/DuxTextView.m#L797

于 2014-03-29T00:53:05.917 回答