Setting tableHeaderView height dynamically Setting tableHeaderView height dynamically ios ios

Setting tableHeaderView height dynamically

Copied from this post. (Make sure you see it if you're looking for more details)

override func viewDidLayoutSubviews() {    super.viewDidLayoutSubviews()    if let headerView = tableView.tableHeaderView {        let height = headerView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize).height        var headerFrame = headerView.frame        //Comparison necessary to avoid infinite loop        if height != headerFrame.size.height {            headerFrame.size.height = height            headerView.frame = headerFrame            tableView.tableHeaderView = headerView        }    }}

Determining the header's frame size using


as suggested in the answers above didn't work for me when my header view consisted of a single multiline label. With the label's line break mode set to wrap, the text just gets cut off:

enter image description here

Instead, what did work for me was using the width of the table view and a height of 0 as the target size:

header.systemLayoutSizeFitting(CGSize(width: tableView.bounds.width, height: 0))

enter image description here

Putting it all together (I prefer to use an extension):

extension UITableView {    func updateHeaderViewHeight() {        if let header = self.tableHeaderView {            let newSize = header.systemLayoutSizeFitting(CGSize(width: self.bounds.width, height: 0))            header.frame.size.height = newSize.height        }    }}

And call it like so:

override func viewWillLayoutSubviews() {    super.viewWillLayoutSubviews()    tableView.updateHeaderViewHeight()}

More condensed version of OP's answer, with the benefit of allowing layout to happen naturally (note this solution uses viewWillLayoutSubviews):

override func viewWillLayoutSubviews() {    super.viewWillLayoutSubviews()    if let header = tableView.tableHeaderView {        let newSize = header.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)        header.frame.size.height = newSize.height    }}

Thanks to TravMatth for the original answer.