Swift macOS SegmentedControl Действие не вызывается - PullRequest
0 голосов
/ 17 января 2019

Описание

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

Итак, в ParentViewController я добавил ChildViewControllers следующим образом:

/// 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 Ответ

0 голосов
/ 17 января 2019

РЕШЕНИЕ

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

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


Фон

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

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

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

class NSSegmentedControl : NSControl
class NSButton : NSControl

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

Обсуждение

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

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

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

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

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

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

Параметры

theAction

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

theTarget

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

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

...