Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I route menu actions to an NSViewController inside a window?

I have a menu item inside the main app menu and I’d like to route its action to a view controller (NSViewController). The interface hierarchy looks like this: There’s a main app window controller by an NSWindowController. Inside the window there’s a split view, and the right view in the split view is controlled by the NSViewController.

Window + NSWindowController
    `-- NSSplitView
           `-- NSView
           `-- NSView + NSViewController

The menu item is connected to First Responder in the Interface Builder. The view controller in question implements the appropriate method, but the menu item stays disabled. When I move the method to the NSWindowController, the menu item gets enabled.

I figured I need to get the view controller to the responder chain, so I set it as the nextResponder for the window controller; no cigar. What am I doing wrong?

like image 647
zoul Avatar asked Jul 12 '12 13:07

zoul


1 Answers

In the end I added a base class for my window controllers and made it forward calls to the “child” controllers:

- (id) childControllerForSelector: (SEL) selector
{
    for (id controller in [childControllers copy])
        if ([controller respondsToSelector:selector])
            return controller;
    return nil;
}

- (BOOL) respondsToSelector: (SEL) selector
{
    return [super respondsToSelector:selector] ? YES :
        [self childControllerForSelector:selector] ? YES :
            NO;
}

- (void) forwardInvocation: (NSInvocation*) invocation
{
    id child = [self childControllerForSelector:[invocation selector]];
    [invocation invokeWithTarget:child];
}

- (NSMethodSignature*) methodSignatureForSelector: (SEL) selector
{
    NSMethodSignature *signature = [super methodSignatureForSelector:selector];
    if (!signature) {
        id child = [self childControllerForSelector:selector];
        signature = [child methodSignatureForSelector:selector];
    }
    return signature;
}

It’s a lot of code, but it’s a general solution that keeps the controller code free from ad-hoc forwarding. Hopefully it’s not too much magic.

like image 116
zoul Avatar answered Sep 22 '22 16:09

zoul