NSResponder定义了许多与键盘操作相关的操作,例如moveUp:
,moveUpAndModifySelection:
和moveToBeginningOfLine:
。除了通过按下修饰键而触发的操作(ex moveUp:
只是Up
箭头键),我无法获得任何要调用的操作在我的自定义NSView
上。
以下是设置:
Custom View
添加到主窗口。NSView
STView
STView
只会覆盖acceptsFirstResponder
以返回YES
在此设置中,我的STView
实例将按预期正确接收所有键盘事件(包括Ctl-A
和performKeyEquivalent:
中包含keyDown:
修饰符的事件。下面的讨论都注释了这两种方法。)
如果我提供了moveUp:
的实现,正如NSResponder
中所定义的那样,当用户按下moveUp:
箭头键时,Up
会正确调用moveUp:
。
每当使用修饰键按下Up
箭头键时,也会调用Ctl-Up
。当一个修饰键被保持时(e.x。:Ctl-Up
)我希望能够调用适当的键盘动作方法。
前:
moveUp:
- > scrollPageUp:
(预期:Alt-Up
)moveUp:
- > moveToBeginningOfParagraph:
(预期:Shift-Up
)moveUp:
- > moveUpAndModifySelection:
(预期:Command-Up
)moveUp:
- > moveToBeginningOfDocument:
(预期:NSApplication sendEvent
)此模式会针对所有键/修饰符组合重复。
Apple的文档中的两个方面似乎相关:
通过阅读该文档,系统似乎负责将关键事件映射到适当的关键操作。事实上,当没有按下修改键时,这适用于我。但是当按下修饰键时,事件就像任何其他事件一样被处理并通过正常的响应者链。
(我可以看到通过NSApplication sendAction:to:from:
传入的修饰键事件,但永远不会调用moveUpAndModifySelection:
,继续沿着视图层次结构,我希望在阅读上面的文档之后。< / p>
文档提示可能会以不同方式处理文本编辑视图。这些键盘操作是否仅发送到编辑文本的视图?如果没有,那么当用户按下NSView
时,如何在自定义Shift-Up
课程中调用keyDown:
这样的消息?
作为参考,我使用此图表进行键盘绑定,但坦率地说,我已尝试过几乎所有组合,无论是否列出:
在一天结束时,我可能会覆盖keyDown
并手动处理我感兴趣的所有组合,但我希望至少能理解为什么这不起作用按照我的意图。
(请注意,此处的预期应用是允许用户导航项目的网格状视图,非常类似于集合视图。)
任何提示,建议或意见将不胜感激。
更新
如果您在- (void)keyDown:(NSEvent *)theEvent {
...
[self interpretKeyEvents:[NSArray arrayWithObject:theEvent]];
}
moveUp:
然后&#34;纠正&#34;将在您的自定义视图上调用操作。我认为这是因为我感兴趣的操作是类似文本的操作,需要输入管理器解释并转换为适当的操作。
我仍然不完全清楚为什么Up
被正确调用。响应者链中的谁正在识别被按下的moveUp:
箭头键然后发送{{1}}消息?
答案 0 :(得分:3)
这是对你的自我回答的回复,这更像是问题的延伸。
是的,在大多数情况下,有必要调用-[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
处理向上箭头键作为&#34;键盘界面控件&#34;的一部分。这是partially documented,但它不会明确调用-moveUp:
等方法。显然,这就是它的实施方式。
答案 1 :(得分:2)
通过阅读该文档,系统似乎负责将关键事件映射到适当的关键操作。
没有“系统”。 NSResponder的工作原理如下:任意消息(只是一串字符)被放到响应者链的开头(无论键盘焦点是什么)。通常它什么都不做,并将其传递给“下一个”响应者。直到50或60次空操作之后,响应者链没有做任何事情,最终说“是的,我会回应那个!”它做了一些事情。一旦发生这种情况,响应者链中的任何内容都不会知道事件发生了。
响应者通常会触发另一个响应者。例如,如果您为keyDown:
发送Cmd-S
消息,它将一直无所事事,直到最终到达“另存为”菜单项,然后将saveDocument:
置于响应者链的开始,重新遍历整个事情,直到它到达NSDocument,它将执行保存操作。
每当使用修饰键按下
moveUp:
箭头键时,也会调用Up
。当一个修饰键被保持时(e.x。:Ctl-Up
)我希望能够调用适当的键盘动作方法。前:
Ctl-Up
- &gt;moveUp:
(预期:scrollPageUp:
)Alt-Up
- &gt;moveUp:
(预期:moveToBeginningOfParagraph:
)Shift-Up
- &gt;moveUp:
(预期:moveUpAndModifySelection:
)Command-Up
- &gt;moveUp:
(预期:moveToBeginningOfDocument:
)
这并不令人困惑,响应者链对滚动视图或文本视图或任何内容都不了解。它只知道应用程序将keyDown
或mouseDown:
消息推送到链上,毫秒后,scrollPageUp:
消息进入链,或者可能没有。响应者链中有许多东西永远不会被使用。如果你需要它们,它们可以被触发,有些东西将由AppKit触发,但很多都没有。
请注意NSResponder
中的方法列表主要是为了让代码自动完成的开发人员更轻松,并在使用GUI构建界面时填充可用操作列表。您可以将任何 @selector()
放在响应者链上(只要它有一个sender
参数)。并非所有正在使用的都被记录在案。
在一天结束时,我可能只是覆盖keyDown:并手动处理我感兴趣的所有组合,但我希望至少能理解为什么这对我不起作用。
是的。如果可能,您应keyDown:
执行[self moveUpAndModifySelection:self];
之类的操作。所以基本上是一个很大的switch语句或if语句没有太多的逻辑。
无论如何我就是这样做的:https://github.com/abhibeckert/Dux/blob/master/Dux/DuxTextView.m#L797