How to hide UITableViewSections in Swift?

I also wish you could just make an @IBOutlet to a section and hide it, but sadly it seems not, so...

Based on various suggestions here, I've established the following, which doesn't require any interfering with explicit size values, and preserves whatever you may have set on a storyboard/XIB already. It just makes the header nil and row count 0 for any section you want to hide (which results in a size of 0.0).

Obviously, you can configure sectionShouldBeHidden to work however you need; hiding #1 & #3 are just arbitrary examples.

Swift v5

private func sectionShouldBeHidden(_ section: Int) -> Bool {
    switch section {
    case 1, 3: return true
    default: return false
    }
}

override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    if sectionShouldBeHidden(section) {
        return nil // Show nothing for the header of hidden sections
    } else {
        return super.tableView(tableView, titleForHeaderInSection: section) // Use the default header for other sections
    }
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if sectionShouldBeHidden(section) {
        return 0 // Don't show any rows for hidden sections
    } else {
        return super.tableView(tableView, numberOfRowsInSection: section) // Use the default number of rows for other sections
    }
}

Update: Unfortunately, the above is only enough if the style of the table view is Plain. When it's Grouped, there's also additional space added between each section, which needs taking care of too. This extra space is the section's footer, so can be handled like so:

override public func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
    if sectionShouldBeHidden(section) {
        return CGFloat.leastNormalMagnitude // Use the smallest possible value for hidden sections
    } else {
        return super.tableView(tableView, heightForFooterInSection: section) // Use the default footer height for other sections
    }
}

Swift 5:

You can use the delegate method heightForHeaderInSection :

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

Earlier than Swift 5: Use UITableViewAutomaticDimension instead of UITableView.automaticDimension

If it's not working with height 0.0, use height 0.1

If you want no cells in a particular section, use the delegate method:

func numberOfRowsInSection(section: Int) -> Int {
  if (section == 0) {
    return 0
  }
  else {
  // return the number of rows you want
  }
}

Or to a neater switch-case syntax:

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    switch section {
    case 0:
        return 0.0
    default:
        return UITableView.automaticDimension
    }
}

I tested both and they are working fine.


I tried all the solutions here with no success. At the end, adding these delegate methods this one worked:

Swift 5:

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return section == 4 ? 0 : return super.tableView(tableView, numberOfRowsInSection: section)
}

override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return section == 4 ? 0.1 : super.tableView(tableView, heightForHeaderInSection: section)
}

override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
    return section == 4 ? 0.1 super.tableView(tableView, heightForFooterInSection: section)
}

Note that you need to return 0.1 in height, returning 0 won't do it.