Article summary
The fourth item in my Swift Tool Belt is an extension for UITableViewController
. A UITableViewController
is a view controller with a table view that takes up the entire screen. My extension provides a couple of methods to resize the header and footer of a table view.
The Problem
The table view has a header and footer which allows you to put UI controls above and below the data in your table view. The problem is that the header and footer do not participate with Auto Layout.
The height of the header and footer need to be set manually. You can set an initial size for your header in Xcode, but that may not work for all phone sizes or situations where you have dynamic content in your header that you hide/show at runtime.
To demonstrate the problem, I’ve added a header view to my table view. Inside the header view, I’ve added a stack panel with four labels in it. As you can see, when I run the project, all four of my labels do not appear in the header.
The Extension to Solve the Problem
This extension will resize the header or footer to the proper size based on the Auto Layout constraints.
import UIKit
extension UITableViewController {
func sizeHeaderToFit() {
if let headerView = tableView.tableHeaderView {
headerView.setNeedsLayout()
headerView.layoutIfNeeded()
let height = headerView.systemLayoutSizeFitting(UILayoutFittingCompressedSize).height
var frame = headerView.frame
frame.size.height = height
headerView.frame = frame
tableView.tableHeaderView = headerView
}
}
func sizeFooterToFit() {
if let footerView = tableView.tableFooterView {
footerView.setNeedsLayout()
footerView.layoutIfNeeded()
let height = footerView.systemLayoutSizeFitting(UILayoutFittingCompressedSize).height
var frame = footerView.frame
frame.size.height = height
footerView.frame = frame
tableView.tableFooterView = footerView
}
}
}
You can call these functions when your header or footer view content has changed. I usually call them once when my table view controller has initially loaded to set the initial height, then again when the content has changed.
To fix my previous example, I call sizeHeaderToFit
in viewDidLoad
to set the initial height of my header.
override func viewDidLoad() {
super.viewDidLoad()
sizeHeaderToFit()
}
When I run my app, you can see the header resizes appropriately to fit all of the content.
I use this extension anytime I have a header and footer in my table view. Hopefully, you find it useful as well.
Thank you so much, I use your code, that is amazing.