highlights

2017年1月13日金曜日

[Swift3] TableViwControllerのCellの高さを表示後も変えるプログラムを書いた

仕事でTableViewControllerを使ってCellを表示するプログラムを書いていたんだけど、表示するCellの高さが動的に変える必要がでてきました。


例えば上記のようにタップすると広がるCell。仕事ではタップして広がるケースの他に、Cell内の文中に書かれているURLに非同期にアクセスして、OGPを表示する処理も必要でした。Androidだと簡単だけどiOSはめっちゃむずいよAppleさん。


タップして広がるような処理を書くときに使えるのが下記の2通り
  • beginUpdates/endUpdatesを使う方法

  • reloadRowsを使う方法

今回苦労したのがOGPなどを非同期で取得して表示する場合で、毎回URL経由でOGPを取得するのも効率が悪いので、すでに取得済みのOGPのデータはキャッシュするようにしていました。なので、
キャッシュにない場合→非同期でOGP取得後にCellを広げて表示
キャッシュにある場合→Cellを作るときに最初からCellを広げてOGP付きで表示

という処理を組む必要があったのですが
  1. beginUpdates/endUpdatesを使う→キャッシュにある場合、Cellが崩れる
  2. reloadRowsを使う→キャッシュにない場合、Cellの高さが変わらない
という現象が起こってしまいました。Fuck。
それぞれの場合で処理を切り分けました。

override func onLoadOGPItem(async:Bool) {
        super.onLoadOGPItem(async:async)
        
        // 非同期のときはbeginUpdatesとendUpdatesを呼ばないと、高さの変更ができない
        // setup内で行うときは逆に呼んでしまうと描画が崩れる
        // DispatchQueueのmainスレッドで処理するとカクつきが酷くなる
        if async {
            self.tableView.beginUpdates()
            self.hogeView.showOGPView()
            self.tableView.endUpdates()
        } else {
            self.hoge.showOGPView()
        }
    }

それぞれの問題に対応するため、非同期で取得した場合beginUpdates/endUpdatesを呼び、最初から描画する場合は呼ばないようにしました。showOGPViewには設定したConstraintsを外したりisHiddenをfalseにしたりする処理が入っています。

これでやりたいことは実現できたんですが、TableViewControllerを使う時はCellの高さをあまり自前で変えないほうが無難かもしれません。AutoLayoutで初期の高さを変更するぐらいでやめたほうがいい気がします。

0 件のコメント:

コメントを投稿