iOS 5 and Blank UITableView section headers

By October 31, 2011 10:06PM [link]

I have an iOS app which uses UITableViews and custom section header views. Some of the sections are intended to be blank, so my -tableView:viewForHeaderInSection looked like this:

- (UIView*)tableView:(UITableView*)tableView viewForHeaderInSection:(NSInteger)section {
    if (section == STATUSVC_SECTION_STATUS) {
        return nil;
    } else {
        return plainHeaderViewWithText(
                 NSLocalizedString(@"Recent Entries", @"..."),

where plainHeaderVIewWithText() is a funcion I've implemented like this. (I use it in more than one place).

UIView* plainHeaderViewWithText(NSString *str, CGFloat width) {
    // Note: assumes ARC.  If you're not using it, you'll want
    // to send -autorelease or -release to the UIView and UILabel
    UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, 35)];
    [headerView setBackgroundColor:[UIColor chooseYourColorHere]];
    UILabel *headerText = [[UILabel alloc] initWithFrame:CGRectMake(10, 3, width - 10, 18)];
    headerText.font = [UIFont boldSystemFontOfSize:19.0];
    headerText.shadowColor = [UIColor grayColor];
    headerText.shadowOffset = CGSizeMake(0.0, 1.0);
    headerText.text = str;
    headerText.textColor = [UIColor whiteColor];
    headerText.backgroundColor = [UIColor clearColor];
    [headerView addSubview:headerText];
    return headerView;

Starting in iOS 5, though, I started getting unwanted blank headers that looked like this:

Not what I wanted! Looking at the UITableViewDelegate protocol docs, I noticed this bit:

The returned object can be a UILabel or UIImageView object, as well as a custom view. This method only works correctly when tableView:heightForHeaderInSection: is also implemented.

A hah! That must be it. Indeed, the docs for that method mention:

Prior to iOS 5.0, table views would automatically resize the heights of headers to 0 for sections where tableView:viewForHeaderInSection: returned a nil view. In iOS 5.0 and later, you must return the actual height for each section header in this method.

So, the fix is to include this method in my tableview delegate:

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
    if (section == STATUSVC_SECTION_STATUS) {
        return 0.0;
    } else {
        return 22.0;

This gets me back where I wanted to be:

Lesson learned: read the docs and implement the methods they tell you to, even if it looks like you don't need 'em!

Update 2012-04-26: converted code above to ARC

History | Blog |