先日、Xcode10.3でビルドしていたプロジェクトをXcode11.3にアップデートしてiOSアプリを更新しました。
更新内容は以下の通りです。
- Xcodeのバージョンアップ
- Swiftバージョンアップ(3.3 -> 5.0)
- 使っているOSSのアップデート(cocoapods)
- 対応OSバージョンアップ(iOS10〜サポート -> iOS11〜サポート)
各OSでのテスト、複数端末でのテストを行って問題なかったのでリリースしたのですが、一部の端末でアプリが起動しなくなる事がわかりました。
クラッシュログや、TestFlightでのテストの結果、一番初めに表示しているViewのviewDidLoadメソッドでself.navigationControllerがnilである事がわかりました。
現象が発生する端末やOSバージョンには傾向が見られませんが、NGな端末はアプリを再インストールしたり、OSを再起動しても状況は変わりませんでした。
問題のコード
1 2 | let height = self .navigationController?.navigationBar.frame.size.height xxx.size.height = height! // これがダメ |
そもそも、Optionalな値を!で強制的に使用しているのがNGなのですが、今までここでクラッシュした事はありませんでした。
この部分がCallされるのは、AppDelegateのdidFinishLaunchingWithOptionsでViewControllerを初期化して、NavigationConteollerに設定、windowに設定した後のはずです。
そこで、AppDelegateを確認すると以下のようになっていました。
1 2 3 4 5 | : let vc = ViewController() let nv = NavigationController(rootViewController: vc) window.rootViewController = nv : |
想像通り、window.rootViewControllerにNavigationControllerを設定した中でViewControllerのviewDidLoadがCallされていました。
しかしながら、viewDidLoadでnavigationControllerがnilになっています😱
調べてみると、端末によって、window.rootViewControllerに設定したら同じスレッドでそのままviewDidLoadがCallされる場合と、少ししてからCallされる場合の2パターンがあるようです。
なので、viewDidLoadの中で、初期化されている事が前提のコードがあると、それもこけます🧐
明日の為に
- オプショナル型を!で強制展開する時には、必ず成功する確証がある時のみにする
- アプリで使っているデータを初期化する場合は一番初めに行う(viewなどをinitする前)
当たり前の事ですが、今一度確認したいです。
0 件のコメント :
コメントを投稿