iOSのアプリを実機でデバッグしようとしたときに起こった出来事です。
エミュレータ上では自分の思ったとおりに動作しているのになんと実機で実行するとビューの画面そのものが出てこない、という現象にはまりました。
検索をかけてもそんな事例を簡単に発見できるわけもなく、いろいろと調べました・・・。そして、
犯人はinitWithNibNameの中にいる!
というのもばからしいですが、結果がこれでした。
xib(nib)を使った画面設計とinitWithNibName
Interface Builder経由の画面設計は簡単なアプリを作るなら手軽で内部動作を考えないで作ることができるのですが、このとき、対象となるUIViewContollerは必ずinitWithNibNameにより初期化されなければなりません。
つまり、
@interface ViewMain : UIViewController { //変数宣言 } @end //ビューの作成 UIViewController *view = [[ViewMain alloc] initWithNibName:nil bundle:nil];
となるのが普通です。ところが、これにちょっとした落とし穴がありまして、それに引っかかってしまったわけです。
initWithNibNameの第一引数はxib(nib)の名前なんですが
これは、基本的に「ビューを作成したときに読み込まれるxibのファイル名となる」ということを私は知らなかったわけです。ただ、デフォルトの動作として
nilが与えられたとき、対象のクラス名と同じ名前のxib(nib)ファイルがあるものとして初期化を行う
という動作があり、これのおかげでエミュレータ上では正しく動作していました。この「正しく動作する」がくせ者で・・・
エミュレータ上ではファイル名の大文字小文字とクラス名の大文字小文字が区別されないでinitWithNibNameが動作するが、実機では区別されている
私がこれを実装したときのxibのファイル名が「viewmain.xib」とすべて小文字だったわけですね。ところが、インターフェイスの名前は「ViewMain」と単語の先頭が大文字となるように定義していたために
実機上では「ViewMain.xib(nib)が存在しないためにロードできない」と判定されたらしいのです。エミュレータ上ではそれがなぜかスルーして動いていたわけでした。
せめてその動作くらいそろえてもいいのでは?という疑問が残っています。