How to make embedded view controller part of the r

2019-05-16 18:48发布

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.

enter image description here

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?

2条回答
你好瞎i
2楼-- · 2019-05-16 19:35

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. :)

查看更多
可以哭但决不认输i
3楼-- · 2019-05-16 19:42

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.

查看更多
登录 后发表回答