UITableView header dynamic height in run-time

Copied from useyourloaf.com

Swift 5.0

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    guard let headerView = tableView.tableHeaderView else {return}
    let size = headerView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
    if headerView.frame.size.height != size.height {
        headerView.frame.size.height = size.height
        tableView.tableHeaderView = headerView
        tableView.layoutIfNeeded()
    }
}

I like the way it's done here:

• If you want to set your tableview header height dynamically based on it's content, just call self.tableView.layoutTableFooterView() right after you have set your headerView as TableViewHeader (so after self.tableView.tableHeaderView = view )

• If you need to update your tableview header height on runtime, also call self.tableView.layoutTableFooterView() right after you have updated the values of your tableview header.

(This obviously also works with tableviewFooters, though, is not to be used for sectionHeaders/Footers)

extension UITableView {

    //Variable-height UITableView tableHeaderView with autolayout
    func layoutTableHeaderView() {

        guard let headerView = self.tableHeaderView else { return }
        headerView.translatesAutoresizingMaskIntoConstraints = false

        let headerWidth = headerView.bounds.size.width
        let temporaryWidthConstraint = headerView.widthAnchor.constraint(equalToConstant: headerWidth)

        headerView.addConstraint(temporaryWidthConstraint)

        headerView.setNeedsLayout()
        headerView.layoutIfNeeded()

        let headerSize = headerView.systemLayoutSizeFitting(UILayoutFittingCompressedSize)
        let height = headerSize.height
        var frame = headerView.frame

        frame.size.height = height
        headerView.frame = frame

        self.tableHeaderView = headerView

        headerView.removeConstraint(temporaryWidthConstraint)
        headerView.translatesAutoresizingMaskIntoConstraints = true
    }

}

source


I am guessing you are talking about section headers of table view here. If that is so you can absolutely use auto layout for section headers.

Use the below two code in viewDidLoad:

tableView.sectionHeaderHeight = UITableViewAutomaticDimension
tableView.estimatedSectionHeaderHeight = 36;

Now in viewForHeaderInSection: try the below code just to get an idea how things are working out. Change it according to your requirement.

func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    let label: UILabel = {
       let lb = UILabel()
        lb.translatesAutoresizingMaskIntoConstraints = false
        lb.text = "HEADER \(section) with a loooooooooooooooonnngngngngngngngng texxxxxxxxxxxxxxxxt"
        lb.textColor = .black
        lb.backgroundColor = .yellow
        lb.numberOfLines = 0
        return lb
    }()

    let header: UIView = {
        let hd = UIView()
        hd.backgroundColor = .blue
        hd.addSubview(label)
        label.leadingAnchor.constraint(equalTo: hd.leadingAnchor, constant: 8).isActive = true
        label.topAnchor.constraint(equalTo: hd.topAnchor, constant: 8).isActive = true
        label.trailingAnchor.constraint(equalTo: hd.trailingAnchor, constant: -8).isActive = true
        label.bottomAnchor.constraint(equalTo: hd.bottomAnchor, constant: -8).isActive = true
        return hd
    }()
    return header
}

I'm using XCode 10.3 and this is my solution worked with your second solution using table header view.

First, you would create a separating view with xib file, for example with a label inside. And you apply the constraints for this label, top, left, bottom, right to the cell's container view. And set numberOfLines = 0.
Example image
Update your awakeFromNib() function inside your view class.

override func awakeFromNib() {
    super.awakeFromNib()
    ourLabel.translatesAutoresizingMaskIntoConstraints = false
}

Second, on your viewController, setup your tableView:

tableView.sectionHeaderHeight = UITableView.automaticDimension
tableView.estimatedSectionHeaderHeight = 64

Remember don't delegate this method:

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat

because we set the constraints of our view already.

Finally, you return it on the delegate method

func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?

the view for header.

let view = UINib(nibName: String(describing: SimpleHeaderTitleView.self), bundle: nil).instantiate(withOwner: nil, options: nil)[0] as! SimpleHeaderTitleView
 view.ourLabel.text = "Your longgggg text"
 return view



Done! Check it works.