【发布时间】:2017-06-07 12:37:23
【问题描述】:
我有一个NSTextView 子类(Obj-C),它通过标准机制实现完成(实现completionsForPartialWordRange:indexOfSelectedItem: 和rangeForUserCompletion 等)。过去,AppKit 会通过两种用户操作之一自动调用完成:按下 command-。 (命令周期),或按 esc(退出)。我刚刚切换到新的“2016 年末”MacBook Pro,同时从 10.11 升级到 10.12。代码完成不再适用于我的应用程序。当没有人响应这些按键时,我只是从响应者链的深处接到NSBeep() 的电话。 NSTextView 的 complete: 方法永远不会被命中(调试器说)。
我怀疑这是因为 Apple 做出了改变。我注意到complete:(https://developer.apple.com/reference/appkit/nstextview/1449359-complete?language=objc)的文档已更改;以前说complete:是esc触发的,但现在说是F5触发的(在我的机器上似乎也不起作用,但功能键映射总是奇怪且难以理解,所以谁知道呢)。
我通过覆盖 doCommandForSelector: 来打印 AppKit 正在尝试的选择器,然后调用 super.事实证明,按下esc 现在会导致doCommandForSelector: 被cancelOperation: 和cancel: 调用,然后按下命令-。现在导致cancel:。这是有道理的,因为那些键是用来取消面板等的,但这里没有涉及面板,没有取消操作等。
我的问题是:让我恢复旧行为的最佳方法是什么?换句话说,在 10.12 及更高版本上,我仍然想要 esc 和 command-。在我的应用程序中调用 complete:。我找到了 Apple 的关于通过 plist 文件更改键绑定的文档,但这似乎不是正确的方法。也许我应该做一个keyDown: 覆盖,但我认为那些因为键事件合并、国际键盘上键代码解释等方面的复杂性而气馁;我的理解是,这通常太低,无法干预事件处理。相反,我认为我应该以某种方式修改interpretKeyEvents: 的行为,将我想要的键绑定到complete:,但我不知道如何在代码中做到这一点。
【问题讨论】:
-
关于
keyDown:不是这样做的正确方法,请注意例如Apple 的文档 (developer.apple.com/library/content/documentation/Cocoa/…) 说“它可以使用NSEvent的字符方法提取事件对象的字符并解释这些字符以查看它们是否与已知的键盘操作相关联。如果是,它会调用适当的操作方法本身或超级视图。不鼓励这种方法。" -
我想他们改变了功能键映射是因为触摸栏取代了功能键。你看过这个文件(developer.apple.com/library/content/documentation/TextFonts/…)吗? “拦截关键事件”部分讨论了使用委托来捕获输入并使用 textView:doCommandBySelector: 为文本视图执行操作。
-
是的,我知道那个医生。它似乎没有解释的是应用程序如何更改键绑定。即,我怎样才能使它在我的应用程序中逃逸转化为对
complete:的调用,就像以前一样,而不是对cancel:的调用?提到了用户如何在他们的 ~/Library 文件夹中使用 plist 定义自定义键绑定,但我没有看到任何关于在代码中更改特定应用程序中的绑定的任何内容。这似乎是一个奇怪的疏忽。 -
默认键绑定是 option-Escape 也是 F5。
-
是的,这是苹果出于某种原因似乎忽略的领域之一。我认为最好的办法是覆盖 keyDown: 并使其尽可能无创。 ~/Library 中 pList 的问题是我认为它是全球性的,而不是特定于您的应用程序。因此,无论是覆盖 keyDown:,还是使用委托或实现您自己的键绑定系统(因为 Apple 不支持动态键绑定),但这可能是代码的痛苦。我在我的应用程序上遇到了这个问题,它需要一种模式来禁用除 6 个键 + 键盘快捷键之外的所有键。我最终覆盖了 keyDown:.
标签: objective-c macos nstextview