Interface Builderを使わずにMacアプリケーション作成 - nib検証篇 1
アプリケーション起動時に実行されるmain()関数
int main(int argc, char *argv[])
{
return NSApplicationMain(argc, (const char **)argv);
}
アプリケーションの起動とは、つまりmain.m
内に定義されているmain()
関数を実行すること。戻り値型はint
で、これはNSApplicationMain()
関数で発生したループ(後述)が終了したときに返される値のようだ。
この中で指定されているNSApplicationMain()
関数は、AppKit.framework
内のNSApplication
クラスで定義されている。NSApplication
クラスの継承関係はNSObject > NSResponder > NSApplication
の順。
NSApplicationMain()関数の処理内容
NSApplicationMain()
関数の実装は公開されていないが、NSApplication
クラスリファレンスにて概要は公開されていたので引用する。
void NSApplicationMain(int argc, char *argv[])
{
[NSApplication sharedApplication];
[NSBundle loadNibNamed:@"myMain" owner:NSApp];
[NSApp run];
}
これはNSApplicationMain()
の動作を例として表した類似コードであり、上記の通りに実装されているわけではない。この処理の概要は次のようになる。
-
+ (NSApplication *)sharedApplication
クラスメソッドがアプリケーションオブジェクトを作成しNSApp
グローバル変数に代入- これはシングルトンなインスタンス
- 指定のxib(からコンパイルされたnib)をロードする
-
NSApp
に対して- (void)run
メソッドを送信- このメソッドは
NSApplication
で定義 -
- run
によってメインイベントループが開始する - このループは
- stop:
や- terminate:
を送信するまで継続する
- このメソッドは
loadNibNamed:owner:について
注意すべきなのはOS X 10.8では+ loadNibNamed:owner:
メソッドはDeprecatedである点。なので、10.8より定義された- loadNibNamed:owner:topLevelObjects:
を使っていると思われる。これはインスタンスメソッドなので、推測される実装はおそらく以下のようなもの。(13/4/21追記:ここで間違った情報を記載してしまいました。nib検証篇 4で扱っています。)
起動時に読み込むxibはどこで指定しているか
これは(Project Name)-info.plist
内のMain nib file base name
Keyで指定されている。この指定を変更するとどうなるか。
Main nib file base nameに該当しないファイル名fooを指定した場合
2013-04-20 14:01:10.489 withoutIB[1386:303] Unable to load nib file: foo, exiting
- アプリケーション withoutIB は__起動しない__。
Main nib file base nameを空欄にした場合
2013-04-20 14:01:38.213 withoutIB[1399:303] Could not connect the action buttonPressed: to target of class NSApplication
2013-04-20 14:01:38.214 withoutIB[1399:303] Could not connect the action buttonPressed: to target of class NSApplication
2013-04-20 14:01:38.215 withoutIB[1399:303] Could not connect the action buttonPressed: to target of class NSApplication
2013-04-20 14:01:38.215 withoutIB[1399:303] Could not connect the action buttonPressed: to target of class NSApplication
- この時点でアプリケーション withoutIB は__起動している__。
- ただしメニューバーにはアップルメニューとアプリケーションメニューの二つのみ表示。
- アプリケーションメニューの中身は空でcmd+Qといった標準操作も受け付けない。
- 興味深いのは、4回エラーを出している点。
仮説
nibを読み込むときの処理を全てコードで記述すれば、Interface Builderを用いずにアプリケーションを起動させることができるか?*1
次回に続きます。
注釈
*1: 掲載当時nibの必要性についての検証が不十分な状態での仮説です。現在は、nibは必要と結論が出ていますのでご了承ください。(13/4/24追記)
Discussion