Cocoa 未在自定义ViewController或View上调用向下键(带:),仅在WindowController上调用

Cocoa 未在自定义ViewController或View上调用向下键(带:),仅在WindowController上调用,cocoa,nsview,xcode-storyboard,nswindowcontroller,keyboard-input,Cocoa,Nsview,Xcode Storyboard,Nswindowcontroller,Keyboard Input,我已经将我的非基于文档的macOS应用程序的大部分核心功能移到了一个定制的嵌入式框架中 应用程序代码有一个带有初始窗口的标准主情节提要,该窗口有一个“窗口内容”关系/转换为指向嵌入框架内情节提要的情节提要引用。其中有一个自定义的NSViewController子类和一个自定义的NSView子类 我想在框架内对所有输入事件处理代码进行分组,这意味着在自定义的NSView子类上实现mouseDown(with:),瞧,当我在应用程序窗口内单击时,它会被调用。到目前为止,一切顺利 接下来,我实现了ke

我已经将我的非基于文档的macOS应用程序的大部分核心功能移到了一个定制的嵌入式框架中

应用程序代码有一个带有初始窗口的标准主情节提要,该窗口有一个“窗口内容”关系/转换为指向嵌入框架内情节提要的情节提要引用。其中有一个自定义的
NSViewController
子类和一个自定义的
NSView
子类

我想在框架内对所有输入事件处理代码进行分组,这意味着在自定义的
NSView
子类上实现
mouseDown(with:)
,瞧,当我在应用程序窗口内单击时,它会被调用。到目前为止,一切顺利

接下来,我实现了
keyDown(使用:)
来类似地处理键盘输入。但是,在运行时,它不会被调用,相反,我会听到恼人的嘟嘟声(
NSBeep

我尝试在视图控制器上实现
keyDown(使用:)
,但都是一样的

最后,我尝试在我的
NSWindowController
子类上实现密钥处理程序,这确实有效

因此,我可以通过如下方式转发事件来解决此问题:

class WindowController: NSWindowController {

    override func keyDown(with event: NSEvent) {
        contentViewController?.view.keyDown(with: event)
    }
}
,但这是非常不雅的。我宁愿不要用输入逻辑污染应用程序代码

然而,这似乎与嵌入框架无关。从“Cocoa App”模板中,并确认只有在窗口控制器代码上实现时才会调用
keyDown(with:)
,而不是在视图或视图控制器端

在基于情节提要的应用程序中,如何在视图或视图控制器(而不是窗口或窗口控制器)上调用
键下键(使用:)
(这样我就可以将其从主应用程序移到嵌入式框架中)


编辑:问题已标记为重复。我尝试了回答另一个问题时指出的解决方案(即,重写
acceptsFirstResponder
以返回
true
)。这解决了我的最小演示项目中的问题,但当我在我的完整应用程序上尝试时,它仍然不起作用(在发布此问题之前,我确实看到了这个问题,并尝试在我的应用程序中覆盖
acceptsFirstResponder

我现在将尝试修改我的最小poject,看看是否可以在主应用程序中报告该问题


编辑2:我已将最小项目重构为:

  • 将视图控制器发送到单独的故事板
  • 将视图控制器的故事板和表示的类(自定义视图、自定义视图控制器)发送到单独的嵌入式框架 现在,基本设置与我的应用程序的设置一致,但仍然无法在最小的项目中重现问题。我会进一步调查


    编辑3:我无法在最小项目上重现该问题。 在我的应用程序的自定义视图中,我实现了:

    public override var acceptsFirstResponder: Bool {
        return true
    }
    
    public override func performKeyEquivalent(with event: NSEvent) -> Bool {
        let retVal = super.performKeyEquivalent(with: event)
        return retVal
    }
    
  • 启动时,
    acceptsFirstResponder
    被调用两次
  • 当按任意键时,
    performKeyEquivalent(with:)
    也会被调用两次。检查上面的中间变量
    retVal
    ,可以发现超类的实现总是返回
    false
    。从该方法返回后,将调用
    NSBeep()
    ,而
    keyDown(with:)
    不会被调用
  • 如果我强制返回
    true
    ,而不是
    super.performKeyEquivalent(with:)
    ,我可以避免调用
    NSBeep()
    (但是
    keyDown(with:)
    仍然没有调用…)

  • 编辑4(最终版):

    出于绝望,我清除了应用程序主情节提要中窗口控制器的身份检查器的“自定义类”字段(默认为
    NSWindowController

    突然,我的自定义视图的
    向下键(带:)
    开始被调用

    我恢复了自定义类以进行确认

    它仍然有效

    我清理生成文件夹并重试

    它仍然有效


    现在,即使在我的主应用程序上,我也无法再重现这个问题。我真的不知道该说什么……

    按键事件被发送给第一响应者。查看@Willeke的可能副本查看我的编辑。按键事件发送给第一响应者。查看@Willeke的可能副本查看我的编辑。