iOS8のUITableViewの自爆機能について(笑)
先日まとめた「iOS8向けアプリ開発時の注意点」に続き、「iOS8の自爆機能について(笑)」にも多くの方が見に来られた様で何よりです。
なお、今までのiOS関連のエントリは、こちらに一覧としてまとめてあります。
先の投稿を公開後、iOS8のUITableViewにはとんでも無く酷い自爆機能が不具合としてある事がわかりました。
そこで、備忘録を兼ねて情報提供したいと思います。
間違いなどがありましたならば、ご指摘下さい。
なお、この問題はBugReport済みですが、いつ直るのかはわかりません。
既に問題が発生するiOS8.0.xはシェア拡大中ですので、知って置いて損は無いかと思います。
ちなみに、iOS8.1 Betaのシミュレータでも同じように発生する事は確認しています。
iOS8のUITableViewの自爆機能とは
iOS8関連のアプリ開発、メンテナンスを行っている方であれば薄々感じていると思いますが、iOS8は不具合が多いですね。
そして、Apple自身が余り使用しない機能に関してはまともにテストをしていない様に見えます。それ位酷いですね。
今回見付けたUITableViewの自爆機能は、発動の条件が揃うと以下の様な事になります。
- アプリが固まる (UIViewのアニメーション描画も途中で止まります)
- OSの動作がおかしくなる
- Homeボタンが利かなくなる時がある
- ステータスバーの時間表示がおかしくなる (時計が更新されないパターンもあり)
- 暫くするとアプリがクラッシュ(数分間。何もしないと10分以上。)
実に嫌な不具合ですね。
テストしていない事が良くわかりますね(笑)
実際にはアプリが固まると言うよりもUIKit内部で無限ループで暴走している様で、Homeボタンが利かなくなる、ステータスバーの表示がおかしくなる等々散々な問題が出てユーザーは大混乱状態になる事は必至だと思います。
そして、アプリが落ちる、固まる、そしてOSが落ちた際のユーザーの怒髪天時の評価書き込みはどのようなものなのかは皆さんは良くご存じだと思います(笑)
まあ、Androidで音ファイルをある程度読み込むとOS自体を落とせる、という問題よりはマシなのかも知れません(笑)
この様な酷い自爆機能は、きちんと対応しないとかなり危険な事は理解して頂けたかと思います。
iOS8のUITableViewの自爆機能の発動条件
自爆機能の発動条件は2つあります。
その2つが揃うと発動します。
まず、1つ目の条件です。
UITableViewには幾つかの一覧更新メソッドが提供されていますが、その更新メソッドの内、以下のメソッド呼び出しが発動条件の1つです。
- (void)reloadSections:(NSIndexSet *)sections
withRowAnimation:(UITableViewRowAnimation)animation;
Sectionを更新するメソッドです。
余り使われていないかも知れませんが、機能として提供されているのであれば使いますよね(笑)
2つ目の発動条件は、以下の通りです。
- UITableViewCell.accessoryViewプロパティにUIViewを設定。
ここで言うUIViewとは素のUIViewだったり、UISwitch等のUIViewのサブクラスの事です。
設定アプリの様に右側にUISwitchを付ける場合やボタン等を付ける際に使用している事も多いかと思います。
上記2つの条件が揃うと確実に問題が発生します。
つまり、UITableView@reloadSectionsメソッドで更新するSectionsの中にUITableViewCell.accessoryViewプロパティにUIViewを設定しているとこの自爆機能が発動し、アプリが固まる等の問題が発生します。
ただし、UITableViewCell.accessoryViewプロパティにUIViewを設定していないSectionだけの更新時は発生しません。
iOS8のUITableViewの自爆機能の回避方法
この問題は、Crash Logを見る限り、UITableViewCellLayoutManager辺りが無限ループに陥って暴走している様に見えます。
流石にUIKit内の問題なのでアプリとしてはどうしようもないですね。
そのため、回避するには上記発動条件のどちらかを行わない事です!
と言い切って終わりでは余りにも寂しいので、少し情報を追記します(笑)
UITableView@reloadSectionsメソッドのwithRowAnimation引数に指定する値は以下の様な違いがありました。
- UITableViewRowAnimationAutomatic -> 発生する。
- UITableViewRowAnimationNone -> 発生しない。ただし、他の何らかの条件が重なると発生する事がある。(他のUIViewを別途貼り付けている場合かも)
上記のwithRowAnimation引数の違いを知っていれば少しはマシになるかも知れません。
ただし、UITableViewRowAnimationNone指定でも確実では無いので、テストはきちんと行う様にしてください。
加えて、以下のUITableViewのメソッドではこの問題は発生しませんでした。
- (void)reloadData;
– 2015年3月11日追記 –
UITableViewCell.accessoryViewプロパティに設定するUIViewのインスタンスを毎回生成させる事でレイアウトの無限ループは回避できる様です。
まとめ
新たなiOS8の自爆機能の原因と解決方法を含めて詳細は理解して頂けましたでしょうか。
この問題のせいでアプリのリリースを遅らせる等、かなり困りました。
他の方の情報を見る限り、Section関連は少し問題が出る所がある様ですので、注意した方が良い様です。
この情報を元に多くの方に役に立てば幸いです。
iOS8の不具合のせいでアニメーションしていた所を無くしたり等、拘って作成した部分を妥協して駄目にしないといけないというのは納得がいかない部分があります。
しかし、流石にアプリが固まるのではどうしようも無いので妥協するしかないですね。
この様にiOS8は開発者を大変困らせる不具合が多いですね。
もし、iOSアプリ開発などで私どもが協力できそうな事がありましたならばご連絡ください。
超強力な開発者が開発のご協力をさせて頂きます(笑)
iOS向けにスクラッチで開発した超高機能テキストエディタ「Wrix」もよろしくお願いします。(iOS8対応版は現在アップデート申請中です。)