问题
I am developing a Mac app using storyboards. I have a window that presents an NSViewController
as its contents, which contains a "container view controller" that embeds an NSSplitViewController
.
The expected behaviour is for the NSSplitViewController
to be part of the responder chain, such that a menu item that triggers the toggleSidebar
action on the first responder actually collapses the item of the NSSplitViewController
that's marked as a sidebar.
However, this simply does not happen and the menu item remains disabled. So my question is, how can-I get the NSSplitViewController
to be part of the responder chain?
回答1:
Check out the nextReponsder
property of NSResponder
. This property defines the responder chain. It's normally set automatically to follow the responder change defined by the Cocoa framework, but you can alter it to insert/skip/divert the chain in a different direction.
For example, at some point (don't ask me when), Cocoa started including the window's controller in the responder chain. So that my apps work consistently on all versions of macOS, I'll include code like this my window's controller:
- (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
, and -awakeFromNib
are all good places to adjust the responder chain so they include, or exclude, whatever objects you want.
回答2:
I ended up getting this to work (in Swift 4) by adding my view controller to the window delegate. After that, my view controller was part of the responder chain (which made application menu items work in my view controller).
//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
}
}
}
I hope that helps someone else. :)
来源:https://stackoverflow.com/questions/47914650/how-to-make-embedded-view-controller-part-of-the-responder-chain