Как сделать встроенный контроллер представления частью цепочки респондента?
Я разрабатываю приложение для Mac, используя раскадровки. У меня есть окно, которое представляет NSViewController
как его содержимое, которое содержит "контроллер представления контейнера", который встраивает NSSplitViewController
,
Ожидаемое поведение для NSSplitViewController
быть частью цепочки респондента, так что пункт меню, который вызывает toggleSidebar
действие на первом респонденте фактически сворачивает элемент NSSplitViewController
это помечено как боковая панель.
Однако этого просто не происходит, и пункт меню остается отключенным. Итак, мой вопрос, как я могу получить NSSplitViewController
быть частью цепочки респондента?
2 ответа
Я заметил, что, возможно, некоторые из этих решений сработали, но я адаптировал ответ более общего назначения из /questions/41369176/derzhite-oba-dochernih-kontrollera-nssplitviewcontroller-v-tsepochke-pervogo-respondenta/41369180#41369180.
Я продлил NSViewController
искать дополнительные цели. Работает наNSSplitViewController
как и любой генерал NSViewController
с детьми).
extension NSViewController {
open override func supplementalTarget(forAction action: Selector, sender: Any?) -> Any? {
if let target = super.supplementalTarget(forAction: action, sender: sender) {
return target
}
for child in children {
var target = NSApp.target(forAction: action, to: child, from: sender) as? NSResponder
if target?.responds(to: action) == false {
target = child.supplementalTarget(forAction: action, sender: sender) as? NSResponder
}
if target?.responds(to: action) == true {
return target
}
}
return nil
}
}
Если вы хотите, чтобы поиск выполнялся только на одном контроллере представления, поместите эту реализацию туда. Это расширение применяется ко всем NSViewController
s и его подклассы.
Я закончил тем, что заставил это работать (в Swift 4), добавив мой контроллер представления к делегату окна. После этого мой контроллер представления был частью цепочки респондента (которая заставляла пункты меню приложения работать в моем контроллере представления).
//Step 1: Add NSWindowDelegate to the controller
class MyViewController: NSViewController, NSWindowDelegate{
override func viewDidLoad() {
super.viewDidLoad()
//Step 2: Add the view controller to the window delegate
if let window = NSApp.windows.first{
window.delegate = self
}
}
}
Я надеюсь, что это помогает кому-то еще.:)
Проверьте nextReponsder
собственностью NSResponder
, Это свойство определяет цепочку респондента. Обычно он устанавливается автоматически, чтобы следовать за изменением респондента, определенным платформой Какао, но вы можете изменить его, чтобы вставить / пропустить / перенаправить цепочку в другом направлении.
Например, в какой-то момент (не спрашивайте меня когда), Какао начал включать контроллер окна в цепочку респондента. Чтобы мои приложения работали согласованно на всех версиях macOS, я добавлю такой код, как этот контроллер моего окна:
- (void)windowDidLoad
{
// Sent when the controller's window has been loaded from the nib
[super windowDidLoad];
NSWindow* window = self.window;
// Make sure this window controller is in the responder chain
NSResponder* nextResponder = window.nextResponder; // get our window's next responder
if (nextResponder!=self)
{
// running earlier OS X that does not include the window controller in the chain: patch us in
self.nextResponder = nextResponder;
window.nextResponder = self;
}
-windowDidLoad
, -viewDidLoad
, а также -awakeFromNib
Все это хорошие места для настройки цепочки респондента, чтобы они включали или исключали любые объекты, которые вы хотите.