iOS 8.0.2 iPad で Could not load NIB in bundle
クラッシュレポートにいくつか Could not load NIB in bundle
のエラーが上がってきていたので調べてみた。
発生しているのはいずれも iOS 8.0.2 で機種は iPad Air, iPad mini 2 が確認された。
アプリ自体は iPhone のみ対応しているアプリで、iPhone ではクラッシュが発生していないので iPhone 専用アプリを iPad で使用している時にのみ起きている問題の様。
原因
クラッシュ時の Exception のメッセージは
Could not load NIB in bundle: 'NSBundle </private/var/mobile/Containers/Bundle/Application/<UUID>/<AppName>.app> (loaded)' with name '<XIBName>'
となっていて、どのNIB (XIB) ファイルが読み込みできなかったのかが分かる。
ビルド後の .app バンドルの中身を覗いてみると
Xcodeで扱っている該当の <XIBName>.xib
はコンパイル後に <XIBName>~iphone.nib
という名称になっていた。
おそらくこの <XIBName>~iphone.nib
が iOS 8.0.2 の iPad からだと読み込み込めてない様子。
他のバージョンの OS では <XIBName>~ipad.nib
が無ければ <XIBName>.nib
を探しそれが無ければ <XIBName>~iphone.nib
を探すという様な処理になっていると思われるが iOS 8.0.2 においては何らかの理由で <XIBName>~iphone.nib
を探すという処理が行われていないと推測される。
発生条件
iOS 8.0.2 の iPad が手元に無いので実際にバグの発生させて確認する事ができないのだけど、レポートから考えると iPhone 専用アプリを iOS 8.0.2 の iPad で使用した時というのが条件としてあると思う。
(他の iOS ではクラッシュは確認できていないがもしかしたら他のバージョンでも起こるかも知れない。)
プロジェクトがユニバーサルアプリになっているとコンパイル後に
<NIBName>~iphone.nib
と <NIBName>~ipad.nib
が生成されていた。
iPad からは後者が読み込まれる事になるのでユニバーサルアプリではクラッシュは起きないはず。
ユニバーサルアプリの設定は Target > General > Deployment Info > Devices で変更可能。
ちなみにデバイス設定が iPad になっていると <NIBName>~ipad.nib
のみが生成される。
iPad 専用アプリは iPhone にはインストールできないので iPad 専用アプリでは問題は起きない。
回避方法
Deployment Target が iOS 8 以降の場合はコンパイル後に
<NIBName>.nib
のみが生成される。
この場合には iPhone, iPad 共に正しくNIBファイルを読み込む事ができるはず。
Deployment Target が iOS 7 以降であってもXIBファイルの Size Classes をオフにしている場合にはコンパイル後に生成されるNIBファイルは <XIBName>.nib
のみになる。
この場合もNIBファイルを正しく読み込む事ができるはず。