Как сделать встроенный контроллер представления частью цепочки респондента?

Я разрабатываю приложение для Mac, используя раскадровки. У меня есть окно, которое представляет NSViewController как его содержимое, которое содержит "контроллер представления контейнера", который встраивает NSSplitViewController,

введите описание изображения здесь

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

Однако этого просто не происходит, и пункт меню остается отключенным. Итак, мой вопрос, как я могу получить NSSplitViewController быть частью цепочки респондента?

2 ответа

Я заметил, что, возможно, некоторые из этих решений сработали, но я адаптировал ответ более общего назначения из /questions/41369176/derzhite-oba-dochernih-kontrollera-nssplitviewcontroller-v-tsepochke-pervogo-respondenta/41369180#41369180.

Я продлил NSViewControllerискать дополнительные цели. Работает наNSSplitViewController как и любой генерал NSViewController с детьми).

extension NSViewController {

    open override func supplementalTarget(forAction action: Selector, sender: Any?) -> Any? {
        if let target = super.supplementalTarget(forAction: action, sender: sender) {
            return target
        }

        for child in children {
            var target = NSApp.target(forAction: action, to: child, from: sender) as? NSResponder

            if target?.responds(to: action) == false {
                target = child.supplementalTarget(forAction: action, sender: sender) as? NSResponder
            }

            if target?.responds(to: action) == true {
                return target
            }
        }

        return nil
    }
}

Если вы хотите, чтобы поиск выполнялся только на одном контроллере представления, поместите эту реализацию туда. Это расширение применяется ко всем NSViewControllers и его подклассы.

Я закончил тем, что заставил это работать (в Swift 4), добавив мой контроллер представления к делегату окна. После этого мой контроллер представления был частью цепочки респондента (которая заставляла пункты меню приложения работать в моем контроллере представления).

//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
    }
  }
}

Я надеюсь, что это помогает кому-то еще.:)

Проверьте nextReponsder собственностью NSResponder, Это свойство определяет цепочку респондента. Обычно он устанавливается автоматически, чтобы следовать за изменением респондента, определенным платформой Какао, но вы можете изменить его, чтобы вставить / пропустить / перенаправить цепочку в другом направлении.

Например, в какой-то момент (не спрашивайте меня когда), Какао начал включать контроллер окна в цепочку респондента. Чтобы мои приложения работали согласованно на всех версиях macOS, я добавлю такой код, как этот контроллер моего окна:

- (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, а также -awakeFromNib Все это хорошие места для настройки цепочки респондента, чтобы они включали или исключали любые объекты, которые вы хотите.

Другие вопросы по тегам