AppKitのNSWindowControllerをNSWindowDelegateにする場合に、なぜだかデリゲートメソッド一式がコールされない現象に悩まされた。調べても原因がよくわからず、NSWindow.delegateの中身を確認しても正しくNSWindowControllerインスタンスが設定されているので、一体どこで通知不能になっているのかが掴めなかった。
一応解決できた方法としては、NSWindowController.showWindow(_:)をオーバーライドし、superのコール前にデリゲートを再設定してあげることでこのコールされない現象を解消できた。
// MyWindowController.swift
override func showWindow(_ sender: Any?) {
window?.delegate = self // ここで delegate 再設定しないとダメ
super.showWindow(sender)
}
// MARK: - NSWindowDelegate
func windowDidBecomeKey(_ notification: Notification) {
// showWindow(_:) tweak によって正しくコールされるようになる
}
func windowDidResignKey(_ notification: Notification) {
// showWindow(_:) tweak によって正しくコールされるようになる
}
しかしどういうことなのだろうこれは。
これ以外に要確認なポイントとして、NSWindowControllerインスタンスが適切に管理されているかどうかがある。要するにウインドウを表示した後にNSWindowControllerインスタンスが自動解放されてしまっていないかどうかを見た方が良い。適当なクラスでNSWindowControllerを保持するプロパティなり用意して、少なくともウインドウが閉じられるまではコントローラも生存していることを保証しなければならない。
let wc = MyWindowController()
wc.showWindow(nil)
// Store the window controller
self.windowControllers.append(wc)