2

我已将基于非文档的 macOS 应用程序的大部分核心功能移至自定义的嵌入式框架。

应用程序代码有一个带有初始窗口的标准主故事板,并且该窗口具有“窗口内容”关系/连接到指向嵌入式框架内的故事板的故事板引用。其中有一个自定义NSViewController子类和一个自定义NSView子类。

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

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

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

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

所以我可以通过转发事件来解决这个问题:

class WindowController: NSWindowController {

    override func keyDown(with event: NSEvent) {
        contentViewController?.view.keyDown(with: event)
    }
}

,但它非常不雅。我宁愿不要用输入逻辑污染应用程序代码。

然而,这似乎与嵌入框架没有任何关系。我从“Cocoa App”模板中整理了一个最小的项目,并确认确实keyDown(with:)只有在窗口控制器代码上实现才被调用,而不是视图视图控制器端。

在基于情节提要的应用程序中,如何keyDown(with:)在视图或视图控制器(而不是窗口或窗口控制器)上被调用?(所以我可以将它从主应用程序移动到我的嵌入式框架)。


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

我现在将尝试修改我的最小诗歌,看看我是否可以在主应用程序中重现该问题。


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

  1. 将视图控制器发送到单独的故事板,
  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
}
  1. 在启动时,acceptsFirstResponder被调用两次。
  2. 按下任何键时,performKeyEquivalent(with:)也会调用两次。检查上面的中间变量retVal表明超类的实现总是返回false。从这个方法返回后,NSBeep()被调用而keyDown(with:)不是被调用。
  3. 如果不是super.performKeyEquivalent(with:)I force-return true,我可以避免调用NSBeep()(但keyDown(with:)仍然没有调用...)

编辑 4(最终):

出于绝望,我在我的应用程序的主故事板中清除了窗口控制器的身份检查器的“自定义类”字段(默认NSWindowController)。

突然,我的自定义视图keyDown(with:)开始被调用。

我恢复了自定义类以确认。

它仍然有效

我清理构建文件夹并重试。

它仍然有效

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

4

0 回答 0