UITableView の reloadSections アニメーションの不具合
ヘッダーをタップすることでセルを開閉できる、アコーディオンのようなテーブルビューを作ったときの話です。ヘッダーだけ残した状態で、セルとフッターを隠したり表示したりを切り替えたくて、 reloadSections:withRowAnimation:
で開閉を実装しました。ところが、とある条件下だと開閉時のアニメーションが期待通りに動作しないことがありました。
問題
ヘッダーだけ残し、セルとフッターが隠されている状態のときに、そのセクションの1つ下のセクションの開閉アニメーションが期待通りに動作していませんでした。隠したいセクションのセルの数を numberOfRowsInSection
で0を返していたのですが、ここに問題があるような気がしています。セクションのヘッダーは表示されているのにセルが0の場合は、セクション毎非表示にするのが正しいのでしょうか。
期待しない動作というのも、言葉では言いづらいのですが、アニメーション(UITableViewRowAnimation.Automatic)の開始位置がずれてしまうというものです。セルの数が0のセクションの下にセルの数が1個以上のセクションがある場合、セルが1個以上のセクションの開閉アニメーションの開始位置が上のセクションのヘッダー部分となってしまっていました。
期待する動作
とりあえず、セクションが空であるかどうかに関わらず、reloadSections
実行時のセルの開閉アニメーションの開始位置が、開閉するセクションのヘッダー部分であることとします。
対応
うまい方法が思いつかなかったので、下記の方法で対処しました。
* numberOfRowsInSection
で0を返していた箇所で1を返す
* cellForRow(at:)
でダミーとなるセルを返す
* tableView(_:heightForRowAt:)
で高さを CGFloat.min
を返す
まとめ
そもそも insertRows(at:with:)
や deleteRows(at:with:)
を使用する手もあるのですが、今回はセルと一緒にフッターも開閉する必要があり、reloadSections
をどうしても使いたかったという背景があります。が、こういう問題があるのはつらいなぁと思いました。