NSSearchField и NSSegmentedControl внутри NSToolbar

Настройка:

Я пишу приложение на основе документов, ориентированное на OS X 10.11, с использованием раскадровок. В главном окне есть NSToolbar с 3-сегментным NSSegmentedControl. При нажатии на сегментированный элемент управления он должен переключать свернутое состояние NSSplitViewItem в горизонтальное или вертикальное NSSplitView. Поведение, которого я пытаюсь достичь, такое же, как в Xcode 7, где сегментированный элемент управления на панели инструментов показывает / скрывает представления Navigator / Debug Area / Utilities.

В настоящее время сегментированный элемент управления отправляет действие первому респонденту. Метод действия реализуется подклассом NSSplitViewController, который затем переключает его состояние NSSplitViewItem в свернутом состоянии.

Проблема:

Проблема в том, что на панели инструментов также есть NSSearchField. Если NSSearchField находится в фокусе или даже если сам сегментированный элемент управления имеет фокус, нажатие на NSSegmentedControl с курсором не приводит к тому, что метод действия правильно перемещается вверх по цепочке респондентов к подклассу NSSplitViewController.

Попытки решения:

Раньше я работал над этой проблемой, используя уведомления вместо цели / действия, но в итоге все получилось слишком запутанным. Другая идея - отправить сообщение контроллеру окна, который затем передаст его контроллеру представления содержимого, который передаст его контроллеру представления вертикального разделения, который затем отправит сообщение (при необходимости) контроллеру представления горизонтального разделения. Хотя я знаю, что это сработает, это также выглядело уродливым решением, когда нужно было добавить код в 2 дополнительных файла, которые просто передавали сообщение, я думал, что это то, чего удалось избежать при использовании цепочки респондентов.

Любые идеи будут очень признательны.

Окончательное решение:

Я понял, что связывание действия сегментированного элемента управления с первым респондентом имеет смысл только в том случае, если важен ключевой контекст представления. В этом случае сегментированный элемент управления должен переключать свернутое состояние элементов разделенного представления в нескольких вложенных разделенных представлениях, независимо от того, какое представление является ключевым.

Определите перечисление для представления областей разделенного представления:

enum SplitViewArea : Int {
    // The raw values must match the order of the segmented control
    case left, top, right
}

Определите протокол, по которому следует переключать разделенную область просмотра:

protocol SplitViewTogglable {
    func toggleSplitViewItem(matching area: SplitViewArea)
}

Реализуйте метод сегментированного управляющего действия в контроллере окна:

@IBAction func segmentedControlSelectionStateDidChange(_ sender: Any) {
    guard let segmentedControl = sender as? NSSegmentedControl else { return }
    guard let area = SplitViewArea(rawValue: segmentedControl.selectedSegment) else { return }
    guard let togglable = contentViewController as? SplitViewTogglable else { return }
    togglable.toggleSplitViewItem(matching: area)
}

Реализуйте метод протокола SplitViewTogglable в подклассе NSSplitViewController:

func toggleSplitViewItem(matching area: SplitViewArea) {
    switch area {
    case .left:
        leftSplitViewItem.isCollapsed = !leftSplitViewItem.isCollapsed
    case .top:
        // Nested NSSplitViewController that adopts SplitViewTogglable
        if let togglable = centerSplitViewItem.viewController as? SplitViewTogglable {
            togglable.toggleSplitViewItem(matching: area)
        }
    case .right:
        rightSplitViewItem.isCollapsed = !rightSplitViewItem.isCollapsed
    }
}

person Andrew    schedule 12.01.2016    source источник


Ответы (1)


NSSplitViewController установлен как contentViewController окна? Как часть цепочки респондентов, ищущих цель действия, окно будет рассматривать ее contentViewController как дополнительную цель, если оно отвечает на селектор действия.

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

person Taylor    schedule 19.01.2016
comment
Это понимание помогло, но в конечном итоге я решил подключить метод действия к оконному контроллеру. Я понял, что подключение к первому респонденту имеет смысл только в том случае, если важен ключевой контекст представления. В моем случае сегментированный элемент управления должен переключать свернутое состояние элементов разделенного представления в нескольких вложенных разделенных представлениях, независимо от того, какое представление является ключевым. - person Andrew; 17.12.2017