Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I hide section headers in iOS 11?

In iOS 11, my section headers always appear, regardless of whether the items are 0 or more.

On iOS 10 devices, my code works and sections disappear when item count is 0. But on iOS 11, the same code has no affect.

func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    if sections[section].items.count > 0{
        return sections[section].title
    }else{
        return nil
    }
}
like image 924
TIMEX Avatar asked Oct 05 '17 20:10

TIMEX


2 Answers

In iOS 11 if you implement only titleForHeaderInSection and return nil, you will not see a header view. But if you also implement viewForHeaderInSection, regardless of what you return, there will be a section.

This alone will not show a section header:

func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    return nil
}

This will show a section header with no title:

func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    return nil
}

func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    return nil
}

So both methods may return nil and the header will be visible. If only titleForHeaderInSection is implemented, no header shows up. That does seem to be a case only in iOS 11. Not sure if it's a bug or a way to force developers chose one method of the two. But the docs confirm this behaviour about titleForHeaderInSection:

"Return Value: A string to use as the title of the section header. If you return nil , the section will have no title."

So nothing about showing or not showing, this method only returns the string for the title. Which makes sense. But what does look like a bug is that returning nil in viewForHeaderInSection will show the section header.

like image 42
Au Ris Avatar answered Oct 27 '22 08:10

Au Ris


To hide a section header for, say, section 0, implement the following method like so:

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    if (section == 0) {
        return CGFloat.leastNormalMagnitude //Now section 0's header is hidden regardless of the new behaviour in iOS11.
    }

    return tableView.sectionHeaderHeight
}

This solution also works for grouped UITableViews, as discussed below.

Update: If you execute reloadSections(..), this solution causes an

NSException of type 'CALayerInvalidGeometry'

If you return 0 in the if statement however, this crash doesn't occur! :)

Therefore, I would say the best solution I have found (atleast for plain UITableViews) is:

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    if (section == 0) {
        return 0
    }

    return tableView.sectionHeaderHeight
}
like image 163
AppreciateIt Avatar answered Oct 27 '22 08:10

AppreciateIt