iOS Quick Tip – programmatically hiding sections of a UITableView with static cells

As we have seen previously, getting a UITableView with static cells to show up can be a bit tricky. You need to remove some of the table methods. However, if you want to dynamically show and hide sections at runtime, you will need add one of them back in and put in a little bit of extra effort.

We’ll start out with a static UITableView that looks like this:

We’ll then add actions for the button touch events, which will set a flag indicating whether or not to hide the middle section:

- (IBAction)HideButtonTouch:(id)sender
{
    hideTableSection = YES;
    [self.tableView reloadData];
}

- (IBAction)ShowButtonTouch:(id)sender
{
    hideTableSection = NO;
    [self.tableView reloadData];
}

We then have to re-implement our previously removed method tableView:numberOfRowsInSection to return the correct number based on whether or not the middle section should be shown:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if(section == 1)
    {
        if(hideTableSection)
            return 0;
        else
            return 1;
    }
    else
    {
        return 2;
    }
}

This gets us closer, but the section header is still showing:

The next thing we have to do is make sure the header doesn’t show up. We do it by overriding theset two methods. Note that we are returning 1 in heightForHeaderInSection – if we return 0, it won’t work.

-(UIView*)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    if(hideTableSection && section == 1)
        return [[UIView alloc] initWithFrame:CGRectZero];
    return nil;
}

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    if(section == 1 && hideTableSection)
        return 1;
    return 32;
}

This gets us most of the way there, but it looks like the gap in between the two sections is a little too large. We can get around this by messing with the size of the footer in a similar manner:

-(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
    if(section == 1 && hideTableSection)
        return 1;
    return 16;
}

-(UIView*)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
    if(section == 1 && hideTableSection)
        return [[UIView alloc] initWithFrame:CGRectZero];
    return nil;
}

Voila! Our section is now properly hidden.

I’m sure this isn’t the ideal way to show and hide sections, but it works well enough for my purposes. And since it took a little bit of effort to figure out, I wanted to share it. Enjoy!

Download the Demo Project

12 Comments

    1. Thanks for the comment. That’s so brilliant it just might work! If you had multiple UITableViews in a UIView, each with a single section, I suppose you could hide them individiaully quite easily. I’ll have to try that in my next project.

      Reply

  1. This is great!

    Now I wish I could programmatically get the numbers for the sections/cells from the static content so I don’t have to change this code when the storyboard changes. Any ideas on that?

    Reply

    1. @mevdev you can call the super function e.g. return [super tableView:tableView viewForFooterInSection:section]; at the end of the function after handling the rest.

      Reply

  2. What about two rows in section 1.
    When I add another cell to section 1 in storyboard. Then
    if(hideTableSection)
    return 1;
    else
    return 2;
    I want two cell, hide the new add one. The first always be visiable.
    The result is strange. return 1, all hide, then return 2, first hide, second show.
    Why? Waiting for your help.

    Reply

  3. You’re a lifesaver. I struggled with this for hours and the trick I was missing was setting the header and footer heights to 1 instead of 0. I wonder if anyone knows why that matters?

    Reply

Leave a Reply to Reinaldo Cancel reply

Your email address will not be published. Required fields are marked *