UITableView : viewForHeaderInSection: not called during reloadData:

The use of tableView:viewForHeaderInSection: requires that you also implement tableView:heightForHeaderInSection:. This should return an appropriate non-zero height for the header. Also make sure you do not also implement the tableView:titleForHeaderInSection:. You should only use one or the other (viewForHeader or titleForHeader).


The trick is that those two methods belong to different UITableView protocols: tableView:titleForHeaderInSection: is a UITableViewDataSource protocol method, where tableView:viewForHeaderInSection belongs to UITableViewDelegate.

That means:

  • If you implement the methods but assign yourself only as the dataSource for the UITableView, your tableView:viewForHeaderInSection implementation will be ignored.

  • tableView:viewForHeaderInSection has a higher priority. If you implement both of the methods and assign yourself as both the dataSource and the delegate for the UITableView, you will return the views for section headers but your tableView:titleForHeaderInSection: will be ignored.

I have also tried removing tableView:heightForHeaderInSection:; it worked fine and didn't seem to affect the procedures above. But the documentation says that it is required for the tableView:viewForHeaderInSection to work correctly; so to be safe it is wise to implement this, as well.


@rmaddy has misstated the rule, twice: in reality, tableView:viewForHeaderInSection: does not require that you also implement tableView:heightForHeaderInSection:, and also it is perfectly fine to call both titleForHeader and viewForHeader. I will state the rule correctly just for the record:

The rule is simply that viewForHeader will not be called unless you somehow give the header a height. You can do this in any combination of three ways:

  • Implement tableView:heightForHeaderInSection:.

  • Set the table's sectionHeaderHeight.

  • Call titleForHeader (this somehow gives the header a default height if it doesn't otherwise have one).

If you do none of those things, you'll have no headers and viewForHeader won't be called. That's because without a height, the runtime won't know how to resize the view, so it doesn't bother to ask for one.


Giving estimatedSectionHeaderHeight and sectionHeaderHeight values fixed my problem. e.g., self.tableView.estimatedSectionHeaderHeight = 100 self.tableView.sectionHeaderHeight = UITableViewAutomaticDimension


Going off rmaddy 's answer, I was trying to hide the Header view and was returning 0.0f for "tableView:heightForHeaderInSection" and a 0 height View from tableView:viewForHeaderInSection .

After changing from return 1.0f to return 0.0f in tableView:heightForHeaderInSection, the delegate method tableView:viewForHeaderInSection was indeed called.

Turns out my desired effect works without having to use "tableView:heightForHeaderInSection"; but this may be useful to others who are having an issue getting "tableView:heightForHeaderInSection" delegate method called.