我正在使用故事板开发Mac应用程序。我有一个窗口,其中显示NSViewController
作为其内容,其中包含一个"容器视图控制器"嵌入NSSplitViewController
。
预期的行为是NSSplitViewController
成为响应者链的一部分,这样触发第一个响应者的toggleSidebar
操作的菜单项实际上会折叠{{1}的项目这标记为侧边栏。
然而,这根本不会发生,菜单项仍然是禁用的。所以我的问题是,我怎样才能让NSSplitViewController
成为响应者链的一部分?
答案 0 :(得分:0)
查看nextReponsder
的{{1}}属性。此属性定义响应者链。它通常会自动设置为遵循Cocoa框架定义的响应者更改,但您可以更改它以向不同方向插入/跳过/转移链。
例如,在某些时候(不要问我什么时候),Cocoa开始在响应者链中包含窗口的控制器。为了让我的应用程序在所有版本的macOS上保持一致,我将包含这样的代码,我的窗口控制器:
NSResponder
- (void)windowDidLoad
{
// Sent when the controller's window has been loaded from the nib
[super windowDidLoad];
NSWindow* window = self.window;
// Make sure this window controller is in the responder chain
NSResponder* nextResponder = window.nextResponder; // get our window's next responder
if (nextResponder!=self)
{
// running earlier OS X that does not include the window controller in the chain: patch us in
self.nextResponder = nextResponder;
window.nextResponder = self;
}
,-windowDidLoad
和-viewDidLoad
都是调整响应者链的好地方,因此它们包含或排除您想要的任何对象。
答案 1 :(得分:0)
通过将视图控制器添加到窗口委托中,最终使它可以工作(在Swift 4中)。之后,我的视图控制器成为响应者链的一部分(这使应用程序菜单项在我的视图控制器中起作用)。
//Step 1: Add NSWindowDelegate to the controller
class MyViewController: NSViewController, NSWindowDelegate{
override func viewDidLoad() {
super.viewDidLoad()
//Step 2: Add the view controller to the window delegate
if let window = NSApp.windows.first{
window.delegate = self
}
}
}
我希望对其他人有所帮助。 :)
答案 2 :(得分:0)
我注意到也许其中一些解决方案已经奏效,但是我改编了https://stackoverflow.com/a/30938725/6938357中更通用的答案。
我在NSViewController
上进行了扩展,以寻找补充目标。适用于NSSplitViewController
以及任何带有孩子的常规NSViewController
。
extension NSViewController {
open override func supplementalTarget(forAction action: Selector, sender: Any?) -> Any? {
if let target = super.supplementalTarget(forAction: action, sender: sender) {
return target
}
for child in children {
var target = NSApp.target(forAction: action, to: child, from: sender) as? NSResponder
if target?.responds(to: action) == false {
target = child.supplementalTarget(forAction: action, sender: sender) as? NSResponder
}
if target?.responds(to: action) == true {
return target
}
}
return nil
}
}
如果只希望它在单个视图控制器上进行搜索,请将该实现放在那里。此扩展适用于所有 NSViewController
及其子类。