keyDown (с :) Не вызывается в Custom ViewController или View, только WindowController - PullRequest
0 голосов
/ 15 апреля 2019

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

Код приложения имеет стандартную основную раскадровку с начальным окном, а окно имеет отношение "содержимое окна" / переход в ссылку на раскадровку, указывающую на раскадровку во встроенной структуре. В этом заключается пользовательский подкласс NSViewController и пользовательский подкласс NSView.

Я хочу сгруппировать весь код обработки входных событий внутри фреймворка, что означает реализацию mouseDown(with:) в пользовательском подклассе NSView, и --lo и вот - он вызывается, когда я щелкаю внутри окна приложения. Пока все хорошо.

Далее Я реализовал keyDown(with:) для аналогичной обработки ввода с клавиатуры. Однако во время выполнения он не вызывается, и вместо этого я слышу раздражающий звуковой сигнал (NSBeep).

Я попытался реализовать keyDown(with:) на контроллере представления , но все равно.

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

Так что я мог бы обойти это, перенаправив событие так:

class WindowController: NSWindowController {

    override func keyDown(with event: NSEvent) {
        contentViewController?.view.keyDown(with: event)
    }
}

, но это очень не элегантно. Я бы предпочел не загрязнять код приложения логикой ввода.

Однако, похоже, это не имеет никакого отношения к встраиванию фреймворков. Я собрал минимальный проект из шаблона «Какао-приложение» и подтвердил, что действительно keyDown(with:) вызывается только при реализации в коде контроллера окна , но не на вид или вид контроллера сторона.

Как мне заставить keyDown(with:) вызываться на контроллере представления или представления (не окна или контроллера окна) в приложении на основе раскадровки? (чтобы я мог переместить его из основного приложения на мой встроенный фреймворк).


Редактировать: Вопрос был помечен как дубликат. Я попробовал решения, указанные в ответах на другой вопрос (а именно, переопределить acceptsFirstResponder для возврата true). Это решает проблему в моем минимальном демонстрационном проекте, но когда я попробовал его в своем полном приложении, оно все равно не работает (я видел этот вопрос и пытался переопределить acceptsFirstResponder в своем приложении перед публикацией этого вопроса).

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


Редактировать 2: Я реорганизовал минимальный проект в:

  1. Отправить контроллер представления на отдельную раскадровку,
  2. Отправка раскадровки контроллера представления и представленных классов (настраиваемое представление, настраиваемый контроллер представления) в отдельную встроенную среду.

Теперь базовая настройка отражает настройки моего приложения во всем, что кажется важным, но все еще не может воспроизвести проблему в минимальном проекте. Я буду продолжать расследование ...


Редактировать 3: Мне не удалось воспроизвести проблему на минимальном проекте. В пользовательском представлении моего приложения я реализовал:

public override var acceptsFirstResponder: Bool {
    return true
}

public override func performKeyEquivalent(with event: NSEvent) -> Bool {
    let retVal = super.performKeyEquivalent(with: event)
    return retVal
}
  1. При запуске acceptsFirstResponder вызывается дважды.
  2. При нажатии любой клавиши, performKeyEquivalent(with:) также вызывается дважды. Проверка промежуточной переменной retVal выше показывает, что реализация суперкласса всегда возвращает false. После возврата из этого метода вызывается NSBeep(), а keyDown(with:) нет.
  3. Если вместо super.performKeyEquivalent(with:) принудительно вернуть true, я могу перевести вызов на NSBeep() (но keyDown(with:) все еще не вызывается ...)

Редактировать 4 (Финал):

В отчаянии я очистил поле «Пользовательский класс» окна контроллера Identity Inspector в основной раскадровке моего приложения (по умолчанию NSWindowController).

Внезапно , мой пользовательский вид keyDown(with:) начинает вызываться.

Я восстановил пользовательский класс для подтверждения.

Это все еще работает .

Я очищаю папку сборки и пытаюсь снова.

Это все еще работает .

Теперь я больше не могу воспроизвести проблему даже в моем основном приложении.Я действительно не знаю, что сказать ...

...