Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to hide UITableViewSections in Swift?

I have a static grouped table view that has 5 sections (all the sections have headers, no footers). I created all of this using a Storyboard. Now, how can I hide the first/top UITableViewSection (including the header). I tried making an outlet to the UITableViewSection but it tells me that it is not valid (undeclared type):

@IBOutlet var section: UITableViewSection!

I did it this way because I was planning on doing:

section.hidden = true

Can it not be done this way?

My delegates and data sources are set up 100% correctly.

like image 346
nick9999 Avatar asked Mar 09 '15 16:03

nick9999


2 Answers

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.

like image 194
saurabh Avatar answered Sep 27 '22 22:09

saurabh


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
    }
}
like image 38
TheNeil Avatar answered Sep 27 '22 20:09

TheNeil