Swift macOS SegmentedControl Действие не вызывается

Описание

Я пытаюсь использовать NSSegmentedControls для перехода между дочерними ViewControllers. ParentViewController находится в Main.storyboard и ChildViewControllers расположены в Assistant.storyboard, Каждый Child ViewController имеет SegmentedControl, разделенный на 2 сегмента, и их основное использование заключается в перемещении между Child ViewControllers. Таким образом, они настроены как momentaryPushIn вместо того, чтобы выбрать один. Каждый Child ViewController использует делегат для связи с ParentViewController.

Поэтому в ParentViewController я добавил Child ViewControllers следующим образом:

/// The View of the ParentViewController configured as NSVisualEffectView
@IBOutlet var visualEffectView: NSVisualEffectView!

var assistantChilds: [NSViewController] {
    get { return [NSViewController]() }
    set(newValue) {
        for child in newValue { self.addChild(child) }
    }
}

override func viewDidLoad() {
    super.viewDidLoad()
    // Do view setup here.
    addAssistantViewControllersToChildrenArray()
}

override func viewWillAppear() {
    visualEffectView.addSubview(self.children[0].view)
    self.children[0].view.frame = self.view.bounds
}

private func addAssistantViewControllersToChildrenArray() -> Void {
    let storyboard = NSStoryboard.init(name: "Assistant", bundle: nil)
    let exampleChild = storyboard.instantiateController(withIdentifier: "ExampleChild") as! ExampleChildViewController
    let exampleSibling = storyboard.instantiateController(withIdentifier: "ExampleSibling") as! ExampleSiblingViewController

    exampleChild.navigationDelegate = self
    exampleSibling.navigationDelegate = self

    assistantChilds = [exampleChild, exampleSibling]
}

Все идет нормально. ExampleChildViewController имеет NSTextField пример. Пока я нахожусь в области действия TextField, я могу запустить действие SegmentedControls. Навигация вперед и назад, как и должно быть. Но как только я покину область TextField, я все еще могу щелкнуть по сегментам, но они не вызывают никаких действий. Они должны иметь возможность перемещаться вперед и назад, даже если TextField не является текущим "первым ответчиком" приложения. Я думаю, что здесь что-то упущено, я надеюсь, что кто-нибудь может мне помочь с этим. Я знаю, что проблема не в NSSegmentedControl потому что я вижу то же самое поведение с NSButton, который настроен как переключатель / флажок, в SiblingViewController. Я просто понятия не имею, что я делаю неправильно.

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

Заранее спасибо!


Дополнительная информация

Для полноты картины:

ParentViewController сам встраивается в ContainerView, который принадлежит RootViewController, Я не могу себе представить, что это имеет какое-либо значение, но таким образом мы не пропускаем что-то.


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


Возможные решения, которые я нашел во время исследования, которые мне не помогли:


Связанные проблемы / темы, которые я нашел во время исследования:

1 ответ

Решение

РЕШЕНИЕ

let parentViewControllerInstance = self.parent as! ParentViewController
segmentedControl.target = parentViewControllerInstance

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


Фон

Хорошо, после нескольких часов чтения документации AppKit я теперь могу ответить на свой вопрос.

Во-первых, отладка пользовательского интерфейса показала, что проблема определенно не в ViewHierarchy.

Поэтому я попытался подумать о природе NSButton и NSSegmentedControl. В какой-то момент я заметил, что оба являются подклассами NSControl.

class NSSegmentedControl : NSControl
class NSButton : NSControl

Документация AppKit гласит:

обсуждение

Кнопки - это стандартный элемент управления, используемый для запуска действий в вашем приложении. Вы можете настроить кнопки со многими различными визуальными стилями, но их поведение одинаково. При нажатии кнопка вызывает метод действия связанного целевого объекта. (...) Вы используете метод действия для выполнения задач вашего приложения.

Жирный текст указывает на ключ решения - связанного с ним целевого объекта. Обычно я определяю действие элемента управления следующим образом:

button.action = #selector(someFunc(_:))

Это заставляет экземпляр NSControl вызывать это:

func sendAction(_ action: Selector?, to target: Any?) -> Bool

Описание параметров из документации:

параметры

Действие

Селектор для вызова на цель. Если селектор равен NULL, сообщение не отправляется.

цель

Целевой объект для получения сообщения. Если объект имеет значение nil, приложение ищет в цепочке респондента объект, способный обработать сообщение. Для получения дополнительной информации о диспетчерских действиях см. Описание класса для NSActionCell.

В заключение у экземпляра NSControl, который запускал метод действия (в моем случае NSSegmentedControl), не было цели для отправки своего действия. Таким образом, он мог только отправить свой метод действия через цепочку респондента - который, очевидно, был нулевым, пока первый респондент находился в другом представлении.

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