【问题标题】:How to add NSViewController to a responder chain?如何将 NSViewController 添加到响应者链中?
【发布时间】:2020-03-19 23:43:23
【问题描述】:

我很难理解和查找有关如何使 NSViewController 接受键和鼠标事件的信息。我在某处读到,为了在 NSViewController 中注册这些事件,应该将其添加到响应者链中,但我找不到如何正确执行此操作的答案。

非常感谢任何形式的帮助!

【问题讨论】:

  • 到目前为止你做了什么?当您运行搜索 [objective-c] [osx] nsview 鼠标事件时,您会发现什么?
  • 我有一个自定义视图控制器,它是 NSViewController 的子类。这个控制器有一个属性,它是一个 NSView。该属性通过 nib 文件(通过 IBOutlet)设置。我知道我可以继承 NSView,并在那里实现鼠标/键事件,并通过通知将它们传递给我的控制器......或者在那里使用 setNextResponder(如下迈克尔所说)。但是,我很好奇我是否可以在不从 nsview 子类化的情况下以某种方式将控制器广告到响应者链。
  • Claus Jørgensen 是正确的,因为并非所有视图控制器都在所有情况下都添加到响应者链中 - 例如,如果视图控制器本身没有作为子视图控制器添加到父控制器(但是它的视图以某种方式通过其他方式添加到视图层次结构中),该视图控制器不会成为响应者链的一部分。

标签: objective-c macos cocoa nsviewcontroller nsresponder


【解决方案1】:

有一个很好的tutorial found at CocoaWithLove.com

总结:您将创建一个 NSView 的子类(例如“EugeneView”),然后该子类将包含一些额外的方法,例如“setNextResponder”和“setViewController”。并且执行这两种方法应该让您的 NSViewController 集成到响应者链中。

【讨论】:

  • 感谢您的回复,迈克尔!我可以在不从 nsview 子类化的情况下以某种方式将 viewController 添加到响应者链吗?
  • @EugeneGordin:是的,下面是我的答案
【解决方案2】:

从 OS X 10.10 Yosemite 开始,不再需要手动将 NSViewController 修补到响应者链中。根据WWDC '14 的说法,“它们在查看后立即自动连接到响应者链中。”

【讨论】:

  • 这是不正确的,并不是所有的视图控制器都会自动连接到响应者链中。
  • @ClausJørgensen:您能否根据特定示例发表评论/否决?另外我想邀请你有一个look at the above video, 20:33
  • 对于 OSX 10.10 和 10.11 及更高版本,我可以确认这可以正常工作,并且可能是首选答案。
【解决方案3】:

或者,如果大多数情况下,您的控制器视图只是一个通用容器,请将您的控制器插入到其视图和子视图之间的响应程序链中。这可以通过控制器 awakeFromNib: 中的这些代码行来完成

对象-C:

[self setNextResponder:self.view];

for (NSView *subview in self.view.subviews) {
    [subview setNextResponder:self]; 
}

斯威夫特:

override func awakeFromNib() {
    super.awakeFromNib()
    self.nextResponder = self.view
    for subview in self.view.subviews {
        subview.nextResponder = self
    }
}

不需要子类化。

【讨论】:

  • 使用此方法可能会导致 *** CFHash() 以 NULL 调用 *** 在针对 10.8.5 时崩溃
  • 这是一个比接受的答案更好的解决方案,因为它更容易(我也无法在第一次尝试时获得接受的答案)。谢谢。
  • 你如何在类 ViewController: NSViewController 中快速做到这一点?
【解决方案4】:

调试时。我注意到 NSViewController view 不接受第一响应者。

您可以通过打印print(viewController.view) //false来确认这一点

对于要添加到响应者链中的 NSViewController,它的视图必须是acceptFirstReponder。这可以通过创建 NSView 的扩展并覆盖其acceptFirstResponder 来轻松完成

extension NSView{
    //making view acceptFirstResponder by default,
    //this will enable NSViewController receive responder event dispatched into responder chain
    open override var acceptsFirstResponder: Bool{return true}
}

这样,您的控制器将添加到响应者链中并接收所有响应者事件。

我的解释可能不太准确,因为我是 Cocoa 的新手。但该解决方案确实运行良好。

我这样做是为了解决我的 ViewController 没有收到 onKeyDown 事件的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-02
    • 2015-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多