Как направить действия меню в NSViewController внутри окна?

У меня есть пункт в главном меню приложения, и я хочу передать его действие контроллеру представления (NSViewController). Иерархия интерфейса выглядит так: есть контроллер главного окна приложения NSWindowController. Внутри окна есть разделенный вид, и правый вид в разделенном виде управляется NSViewController.

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

Пункт меню связан с Первым респондентом в Интерфейсном Разработчике. Рассматриваемый контроллер представления реализует соответствующий метод, но этот пункт меню остается отключенным. Когда я перемещаю метод в NSWindowController, этот пункт меню становится активным.

Я решил, что мне нужно подключить контроллер представления к цепочке респондентов, поэтому я установил его как nextResponder для оконного контроллера; нет сигары. Что я делаю неправильно?


person zoul    schedule 12.07.2012    source источник
comment
Вы можете добавить объект в IB, представляющий ваш Контроллер. Затем свяжите действие меню с IBAction вашего контроллера.   -  person Matthieu Riegler    schedule 12.07.2012
comment
К сожалению, это невозможно, контроллеры просмотра меняются в зависимости от того, что выбрано на левой разделенной панели просмотра.   -  person zoul    schedule 12.07.2012
comment
Затем нужно будет переназначать действие меню каждый раз, когда представление становится фокусом. Чтобы получить доступ к меню te: [[[[NSApp mainMenu] itemWithTitle: @ItemName] меню] itemWithTitle @ ItemName] setAction: @Selector (theSelector)]   -  person Matthieu Riegler    schedule 12.07.2012
comment
Да, это возможный обходной путь (спасибо), но я хотел бы, чтобы он работал официальным способом через цепочку респондентов, потому что переназначение цели для моих пунктов меню вручную - отстой.   -  person zoul    schedule 12.07.2012


Ответы (2)


В конце концов, я добавил базовый класс для своих оконных контроллеров и заставил его переадресовывать вызовы «дочерним» контроллерам:

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

Это много кода, но это общее решение, которое избавляет код контроллера от специальной пересылки. Надеюсь, это не слишком много волшебства.

person zoul    schedule 13.07.2012

Вы можете установить оконный контроллер в качестве делегата окна, чтобы теперь он стал частью цепочки респондентов.

Предполагая, что у вас есть собственный подкласс NSWindowController, вы можете просто перехватить там событие меню и вызвать соответствующие методы в ваших контроллерах.

К сожалению, в документации не рекомендуется вставлять что-либо в цепочке респондентов между различными представлениями и подпредставлениями, поэтому вы не можете просто втиснуть туда свой контроллер представления.

Подробнее здесь, но я беру это вы уже консультировались с этим.

person Monolo    schedule 12.07.2012