如何从 NSTextField 的字段编辑器中拦截击键?

How to intercept keystrokes from within the field editor of an NSTextField?

简介

当我的自定义 NSTextField 位于 "text editing mode" 并且 field editor 已作为 firstResponder 放在其前面时,我不再通过 [=15 获得击键=].我知道击键现在正在通过 field editor 进行路由。网上大部分推荐都是在自定义的delegate中覆盖下面的方法NSTextField:

control(_:textView:doCommandBySelector:)

我确实重写了这个方法,但是好像没有被调用?请参阅下面的代码:

class FocusDelegate: NSObject, NSTextFieldDelegate{

    func control(control: NSControl, textView: NSTextView, doCommandBySelector commandSelector: Selector) -> Bool {

        println("FocusDelegate")
        if commandSelector == Selector("cancelOperation:"){
            println("cancelOperation")
            control.abortEditing()
            return true
        }
        return false
    }
}

我唯一要做的另一件事是将我的自定义 NSTextField 的委托设置为上面 class 的一个实例。我还尝试将上面的方法直接放入自定义 NSTextField class - 它不会导致任何错误,但也不会被调用。

问题

  1. 我在上面让委托调用工作时遗漏了什么?
  2. 除了创建我自己的自定义字段编辑器之外,这是唯一的方法吗? textDidChange(notification: NSNotification) 不能被询问以产生按下的键吗?
  3. 在使用 control(_:textView:doCommandBySelector:) 委托方法时,如何捕获 NOT 具有标准键绑定的键的按下。特别是,我想拦截不映射到任何标准选择器的组合键 "shift+enter" 。 (隐含的问题:你只能映射到 NSResponder 中的标准按键操作方法吗?)

我相信我已经更加清楚地了解 NSTextField 其代表及其 fieldEditor 及其代表的工作方式。是的,每个人都有自己的代表,NSTextField 自动设置为 fieldEditor.

的代表

我正在向主持人添加委托 NSTextField。当 fieldEditorfirstResponder 时,这将 NOT 被调用,这是我所关心的。这也不是上述场景的重要代表。

似乎有用的是使 NSTextField 符合 NSTextViewDelegate 协议并特别覆盖方法:

 func textView(textView: NSTextView, shouldChangeTextInRange affectedCharRange: NSRange, replacementString: String) -> Bool

捕获各种按键。

textDidChange(notification: NSNotification) 中的通知在这种情况下没有用,因为它是在 按键之后报告的。

textView:shouldChangeTextInRange:replacementString: 中截获按下的键并不理想,因为它被调用的时间很晚,例如,当用户从剪贴板粘贴时也会被调用。

一个可能更简洁的方法是截取 textView:doCommandBySelector:,它会被各种特殊键调用,例如制表符、光标、return 和回车,然后您将获得特定的选择器让您确定调用了哪个特殊键。

但是,对于某些键,例如Return(CR)和Enter(ETX),您无法区分它们,因为它们使用相同的“insertNewline :" 选择器。

在这种情况下,您可以检查当前处理的事件是否是按键事件,如果是,请检查它是哪个键。

这是一个快速测试代码,可让您监控选择器名称和涉及的键码:

-(BOOL)textView:(NSTextView *)textView doCommandBySelector:(SEL)commandSelector
{
    NSEvent *ev = self.view.window.currentEvent;
    NSLog (@"selector: %s, key: %d", commandSelector, (int)ev.keyCode);
    return NO;
}