Dynamically Sized Table View Header or Footer Using Auto Layout

I’m trying to support Dynamic Type everywhere I can in my new app. Auto Layout and self sizing table view cells (buggy as they are) makes that a lot easier for the most part. Still, there’s other places that just setting up constraints and changing the font size of a label isn’t enough. The one I’ve just dealt with is a table view header (UITableView().tableHeaderView) with text in it. If I do nothing but set up my constraints and set the header view, the font size changing will just cause extra space to appear or my text to get cut off.

The solution was to override UIViewController().viewDidLayoutSubviews(), get the proper size of the header view based on it’s constraints, set the frame on the header, and reset it as the table header view.

It took me a little while to figure this out, so here’s what I did:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    // Dynamic sizing for the header view
    if let headerView = tableView.tableHeaderView {
        let height = headerView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height
        var headerFrame = headerView.frame

        // If we don't have this check, viewDidLayoutSubviews() will get
        // repeatedly, causing the app to hang.
        if height != headerFrame.size.height {
            headerFrame.size.height = height
            headerView.frame = headerFrame
            tableView.tableHeaderView = headerView
        }
    }
}
Collin Donnell @collin