Я переместил большинство основных функций моего приложения 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: Я реорганизовал минимальный проект в:
- Отправить контроллер представления на отдельную раскадровку,
- Отправка раскадровки контроллера представления и представленных классов (настраиваемое представление, настраиваемый контроллер представления) в отдельную встроенную среду.
Теперь базовая настройка отражает настройки моего приложения во всем, что кажется важным, но все еще не может воспроизвести проблему в минимальном проекте. Я буду продолжать расследование ...
Редактировать 3: Мне не удалось воспроизвести проблему на минимальном проекте.
В пользовательском представлении моего приложения я реализовал:
public override var acceptsFirstResponder: Bool {
return true
}
public override func performKeyEquivalent(with event: NSEvent) -> Bool {
let retVal = super.performKeyEquivalent(with: event)
return retVal
}
- При запуске
acceptsFirstResponder
вызывается дважды.
- При нажатии любой клавиши,
performKeyEquivalent(with:)
также вызывается дважды. Проверка промежуточной переменной retVal
выше показывает, что реализация суперкласса всегда возвращает false
. После возврата из этого метода вызывается NSBeep()
, а keyDown(with:)
нет.
- Если вместо
super.performKeyEquivalent(with:)
принудительно вернуть true
, я могу перевести вызов на NSBeep()
(но keyDown(with:)
все еще не вызывается ...)
Редактировать 4 (Финал):
В отчаянии я очистил поле «Пользовательский класс» окна контроллера Identity Inspector в основной раскадровке моего приложения (по умолчанию NSWindowController
).
Внезапно , мой пользовательский вид keyDown(with:)
начинает вызываться.
Я восстановил пользовательский класс для подтверждения.
Это все еще работает .
Я очищаю папку сборки и пытаюсь снова.
Это все еще работает .
Теперь я больше не могу воспроизвести проблему даже в моем основном приложении.Я действительно не знаю, что сказать ...