はじめに
UITableView
を使用する際に繰り返しの要素はseciton
やcell
を用いて表示することが多いかと思います。
主にこれらがUITableView
のメイン要素となり、各section
のサマリや補足情報をsectionHeaderView
やsectionFooterView
に記載します。
そして、繰り返し要素そのものには直接関係しませんが、繰り返し情報の前提となる条件や全体に対するなんらかの補足情報、
もしくは広告を表示したいとなった場合、UITableView
全体のheader
やfooter
であるtableHeaderView
, tableFooterView
を使用することになるかと思います。
ただし、特にtableFooterView
では独特の癖があり、UIViewController
をchildViewController
化しtableFooterView
に追加しようとした際に少々難儀しました。
次回同様のことがあった際に、対応方法を即座に思い出せるよう記事として残します。
環境設定
以下の環境を使用しています。
- Xcode10.3.0
- Swift 5.0.1
注意点
footerに設定するView自体のレイアウトではauto layoutを使用しない
tableFooterView
のheight
を以下のようにautoLayout
を用いて指定すると、tableFooterView
が正常に表示されません。
例えば下記のような書き方をすると、レイアウトが崩れてしまいます。
footerView.translatesAutoresizingMaskIntoConstraints = false footerView.heightAnchor.constraint(equalToConstant: 50.0)
なお、translatesAutoresizingMaskIntoConstraints
をfalse
にしていてもconstraint
を使用していなければ正常に表示されました。
viewのレイアウトをしてからtableFooterViewに代入する
tableFooterView
に該当のview
を設定してから、footerView
内のsubViewのレイアウトを変更しようとすると変更が正常に反映されません。例えば下記のコードのようにtableFooterView
のsubview
としてfooterInnerView
を追加して、footerInnerView.center = footerView.center
してからtableFooterView
に設定した場合は、正しく中央に配置されますが、tableFooterView
に設定してから先ほどのレイアウトを行うと中央に正しく配置されません。
footerView.backgroundColor = .black footerView.frame.size.height = footerHeight footerView.frame.size.width = UIScreen.main.bounds.width let footerInnerView = UIView(frame: CGRect(x: 0, y: 0, width: 100.0, height: 40.0)) footerInnerView.backgroundColor = .yellow footerView.addSubview(footerInnerView) footerInnerView.center = footerView.center tableView.tableFooterView = footerView
ChildViewControllerをfooterViewに設定する際の注意点
child
化したUIViewController
をtableFooterView
に追加する際にも、同様に追加~レイアウトを行う順番に気をつけないとレイアウト崩れが発生するため注意が必要です。以下のコードではレイアウトがうまくいきますが、tableView.tableFooterView = footerView
の後にviewController.view.frame = footerView.frame
を実行するとレイアウトが崩れます。
// ChildViewController viewController.view.backgroundColor = .blue addChild(viewController) footerView.addSubview(viewController.view) viewController.didMove(toParent: self) viewController.view.frame = footerView.frame tableView.tableFooterView = footerView
また、レイアウトを以下のようにautoLayout
を用いて実現しようとするとレイアウトが崩れるため注意が必要です。
// ChildViewController viewController.view.backgroundColor = .blue addChild(viewController) footerView.addSubview(viewController.view) viewController.didMove(toParent: self) viewController.view.translatesAutoresizingMaskIntoConstraints = false viewController.view.topAnchor.constraint(equalTo: footerView.topAnchor) viewController.view.leadingAnchor.constraint(equalTo: footerView.leadingAnchor) viewController.view.trailingAnchor.constraint(equalTo: footerView.trailingAnchor) viewController.view.bottomAnchor.constraint(equalTo: footerView.bottomAnchor) tableView.tableFooterView = footerView
UIViewController
のchild
化は同じ手続きが多いため、以下のようなメソッドを用意している場合があると思います。
この場合、autoLayout
を使用してレイアウトを決定しているためレイアウトが崩れてしまいます。
UIViewController
をchildViewController
として追加した際のレイアウトがうまくいかなかった際は原因の一つとして疑ってみてください。
extension UIViewController { func addChildViewController(_ child: UIViewController, on containerView: UIView) { self.addChild(child) containerView.addSubview(child.view) child.didMove(toParent: self) child.view.translatesAutoresizingMaskIntoConstraints = false child.view.topAnchor.constraint(equalTo: containerView.topAnchor) child.view.leadingAnchor.constraint(equalTo: containerView.leadingAnchor) child.view.trailingAnchor.constraint(equalTo: containerView.trailingAnchor) child.view.bottomAnchor.constraint(equalTo: containerView.bottomAnchor) } }
まとめ
tableFooterView
を使用する際には以下2点に気をつける必要があります。
- footerに設定するView自体のレイアウトではauto layoutを使用しない
- tableFooterViewにViewを追加する前にレイアウトを済ませておく