xibを使ってソースコードから表示しようとした時にapplicationDidFinishLaunchingが呼ばれなくて困った話(OS X App)
最近は上京してOSX Appを書いている人です。
困りごと(ていうか届かぬ文句)
- AppKitまわりの資料が少ない
- AppKitまわりの資料が古い
- ↑探すくらいならリファリンス読む
- Swiftとの合わせ技だとめったにない
- xibとかの話だとあるわけがない
今回の現象
作りたかったもの
- OS Xアプリで簡易WebブラウザみたいなWindowにWebView乗っけただけのもの。
- NSWindowControllerでWindowおよびその上のViewイベントの管理をする。
- 新しいウィンドウを開くみたいなリンクをクリックしたら新しいWindowControllerを生成する。
- WindowControllerは管理クラスが管理して、Windowを閉じたら管理クラスから抹殺する。
- WindowControllerの動きは共通かつ、Window内でViewの遷移がないからStoryBoardは使わずxibを使う。
やったこと
- StoryBoardファイルは消す
- NSWindowControllerがFiles Ownerのxib(CustomWindow.xib)を作る
- プロジェクト設定のDeployment Info - Main Interfaceを消す
- AppDelegateのapplicationDidFinishLaunchingで↑のxibからWindowControllerのカスタムクラスを生成
func applicationDidFinishLaunching(notification: NSNotification) { var windowController CustomWindowController: = CustomWindowController(windowNibName: "CustomWindow") //... self.window = windowController!.window self.window!.setFrame(NSScreen.mainScreen()!.frame, display: true, animate: true) self.window!.makeKeyWindow() }
- windowDidLoadで管理クラスにWindowControllerを保存、windowWillCloseで管理クラスから削除
ビルド結果
Windowが表示されない。
ていうか、AppDelegateのapplicationDidFinishLaunchingが呼ばれないからWindowが生成されない。
AppDelegateのクラスの宣言時に@NSApplicationMain書けば(デフォルトで書いてあるけど)applicationDidFinishLaunchingが呼ばれると思っていたんだけど違うらしい。
@NSApplicationMain class AppDelegate: NSObject, NSApplicationDelegate { // ...
解決策(スマートではないと思うけど...)
要はapplicationDidFinishLaunchingが呼ばれれば良い。
- 空のMainMenu.xibを用意する。
- Files Owner(NSApplication)とAppDelegateをDelegateで結ぶ
- プロジェクト設定のDeployment Info - Main InterfaceをMainMenuと入れる
まとめ
- だいぶ特殊用途だと思うけど、今回はこんな感じで解決した。
- すげー時間かかった。空のNib作らなくてもいける方法ある気がしたけど、今回はタイムアップでした。
- 今回初めてNSWindowController使った。
- Viewの切り替えがなかったからNSViewController使わなかった。
- いっぱいWindowあって、いっぱいViewを切り替えるアプリを作るのは骨だなあと思った。