I've set up the tableview with correct delegate and datasource linkages.. the reloadData method calls the datasource and the delegate methods except for viewForHeaderInSection:
.
Why is that so?
I've set up the tableview with correct delegate and datasource linkages.. the reloadData method calls the datasource and the delegate methods except for viewForHeaderInSection:
.
Why is that so?
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 the protocol UITableViewDelegate
(I wonder why, any comments?)
That means
If you implement the methods but assign yourself only as the dataSource
for the UITableView
, tableView:viewForHeaderInSection
implementation of yours will be ignored and will never be called.
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.
For research purposes, I have removed my tableView:heightForHeaderInSection:
; it worked fine and didn't seem to affect the procedures above. But the comment doc states that it is required for the tableView:viewForHeaderInSection
to work correctly; so to be safe it is wise to implement this.
@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.
You should implement tableView:heightForHeaderInSection:
and set the height for the header >0.
This delegate method goes along with the viewForHeaderInSection:
method.
I hope this helps.
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return 40;
}
It's worth briefly noting that if your implementation of tableView:heightForHeaderInSection:
returns UITableViewAutomaticDimension
, then tableView:viewForHeaderInSection:
will not be called.
UITableViewAutomaticDimension
assumes that a standard UITableViewHeaderFooterView
will be used that is populated with the delegate method tableView:titleForHeaderInSection:
.
From comments in the UITableView.h
:
Returning this value from
tableView:heightForHeaderInSection:
ortableView:heightForFooterInSection:
results in a height that fits the value returned fromtableView:titleForHeaderInSection:
ortableView:titleForFooterInSection:
if the title is not nil.
I've just had an issue with headers not showing for iOS 7.1, but working fine with later releases I have tested, explicitly with 8.1 and 8.4.
For the exact same code, 7.1 was not calling any of the section header delegate methods at all, including: tableView:heightForHeaderInSection:
and tableView:viewForHeaderInSection:
.
After experimentation, I found that removing this line from my viewDidLoad
made headers re-appear for 7.1 and did not impact other versions I tested:
// _Removing_ this line _fixed_ headers on 7.1
self.tableView.estimatedSectionHeaderHeight = 80;
… so, there seems to be some kind of conflict there for 7.1, at least.
Same issue occured with me but as I was using automatic height calculation from xCode 9, I cannot give any explicit height value as mentioned above. After some experimentation I got solution, we have to override this method as,
-(CGFloat)tableView:(UITableView *)tableView
estimatedHeightForHeaderInSection:(NSInteger)section
{
return 44.0f;
}
Although I have checked both options
from storyboard as apple says, but still I got this weird error.
Please Note: This Error was shown only on IOS-10 version not on IOS-11 version. Maybe it's a bug from xCode. Thanks
Here's what I've found (Swift 4) (thanks to this comment on another question)
Whether I used titleForHeaderInSection or viewForHeaderInSection - it wasn't that they weren't getting called when the tableview was scrolled and new cells were being loaded, but any font choices I made for the headerView's textLabel were only appearing on what was initially visible on load, and not as the table was scrolled.
The fix was willDisplayHeaderView:
func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
if let header = view as? UITableViewHeaderFooterView {
header.textLabel?.font = UIFont(name: yourFont, size: 42)
}
}
Sometimes setting tableview.delegate
or datasource = nil
in the viewWillAppear:
or viewDidAppear:
methods can cause this issue. Make sure not to do this...
I had cut & paste the following two methods from a Swift 2 project into my Swift 3 project which were never called because in Swift 3 these methods must have "-" before the first parameter name.
func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 44.0
}
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = tableView.dequeueReusableHeaderFooterView(withIdentifier: B2BTrolleyHeaderFooterView.reuseIdentifier) as! B2BTrolleyHeaderFooterView
return headerView
}