如何将菜单操作路由到窗口内的NSViewController?

时间:2012-07-12 13:33:40

标签: macos cocoa nsmenuitem nsresponder

我在主应用程序菜单中有一个菜单项,我想将其操作路由到视图控制器(NSViewController)。接口层次结构如下所示:NSWindowController有一个主应用程序窗口控制器。在窗口内部有一个拆分视图,拆分视图中的右视图由NSViewController控制。

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

菜单项连接到Interface Builder中的First Responder。有问题的视图控制器实现了适当的方法,但菜单项保持禁用状态。当我将方法移动到NSWindowController时,菜单项会启用。

我想我需要将视图控制器连接到响应器链,因此我将其设置为窗口控制器的nextResponder;没有雪茄。我做错了什么?

2 个答案:

答案 0 :(得分:3)

最后,我为我的窗口控制器添加了一个基类,并将其调用到“子”控制器:

- (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;
}

这是一个很多代码,但它是一个通用的解决方案,可以使控制器代码免于ad-hoc转发。希望这不是太多魔术。

答案 1 :(得分:2)

您可以将窗口控制器设置为窗口的委托,以便它现在将成为响应程序链的一部分。

假设您拥有自己的NSWindowController子类,则可以在那里捕获菜单事件并在控制器中调用适当的方法。

不幸的是,文档建议不要在各个视图和子视图之间的响应器链中插入任何内容,这样你就不能只在那里挤压你的视图控制器。

更多here,但我认为你已经咨询过了。