【Swift】カスタムなUITableViewの高さを固定→可変にしようとして試行錯誤した話

共通処理部でUITableViewの高さを設定すると、個別に高さ調整したときに困る話

気付くまでに3時間ほどハマったので、こちらにメモ。


いきさつ

Dynamics Type対応に伴い、以下の構成からなる2画面(履歴、お知らせ)についてお知らせ用ViewController内にあるUITableVIewのカスタムセルの高さを可変にしようとした

画面構成

当画面は2つのViewControllerからなり、ページ切り替えで互いのページを切替可能。

PageTwoViewCellのレイアウト構成は以下の通り。両端にお知らせの写真、真ん中に本文(上)と配信日(下)が入る構成。 PageTwoViewCellの構成

両矢印は幅、片矢印は位置設定

やったこと

前準備:PageTwoViewCellをxibでレイアウトし、データの反映をswiftで記載

PageTwoViewCellをxibで設定した構成図

レイアウト上の変更点は以下の通り

結果:セルの高さが固定されており、セルが途中で切れて表示された

PageTwoViewCell セルが途中までの高さで表示

1. 予測した原因1(x):UITextView(本文)にテキスト反映後、UITextViewのintrinsicContentSizeが更新されていない

デバッガで確認したところ、intrinsticContentSizeは更新されているが想定した値よりも小さくなっていることを確認。また、この結果が-1になっていない(参考1)ことからUITextViewのスクロールが正しくオフになっていることを確認 (参考2)

2. 予測した原因2(x):UITextViewをsizeThatFitsし、計算した高さをconstraint等で設定する必要がある?

まず、UITextViewに高さのconstraintを設定。そして、上記テキスト反映直後にsizeThatFitsし、得たCGSizeの高さをcostraintに反映。

当然ながらUITextViewの高さのconstraintとUILabel(配信日)のbottomのconstraintが干渉してしまい、結果として前者が自動削除される。無意味のため元の状態に戻した。

3. 調査(x):UILabelのbottomのconstraintを一旦削除してどうなるか見てみた

以下の様に、UITextViewの表示高さは広がったものの全ては表示されず、UILabelも表示されなくなった

セルのUITextViewが途中で表示されず

4. 1.-3.で詰まったので、PageTwoViewController.mでtableView:heightForRowAtIndexPath: でcellの高さをとりあえず200pxに指定(△)

UITextViewに反映したテキストは全て表示された。ただし、constraintによりその高さは200 - UILabelの高さになってしまう。

5. 問題を簡単化するため、UITextView以外を削除して表示してみる(x)

やはり上図と同様に、セルの高さが固定されていた

6. セルの高さはどこで指定していたか?と思った

そこで、BaseViewController.mを見た

真因:共通のViewControllerでセルの高さを指定していた

そもそもBaseViewController.mにて、両ページのカスタムセルの高さを指定していた。これにより、いくらPageViewController.m側でセルの高さを調整しようとしても以下の処理が優先されていた。

そこで、以下の記述をPageOneViewController.mに移した所、PageTwoViewCellController.mでテーブルのセルが正しく可変高さで表示された。

BaseViewController.m

1
2
3
4
(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return 71;
}

これを踏まえてやったことを振り返ってみると、以下の要員で高さを可変にできていなかった。

反省

あらためて、設計・実装を理解しよう

他のメンバーの書いたコード(今回の箇所)について、コード変更前に関係箇所をメンバーに確認し設計・実装を理解すること。今回のように、いきなり子の部分の実装を変更しようとするのはNGです…。

継承関係のあるコードも見よう

今回のように継承関係のあるViewやViewControllerについて、親側のコードもコード変更にともなう影響を見ておく必要がある。

気分転換や切り替えは大事

4.で詰まったので別のことをして4時間ほど時間を開けて気分転換を行った。その結果、再度取り組んだときに5.および6.の内容にいきつき問題解決につながった