Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hide cells in a UITableView with static cells - and no autolayout crash

I have a table view form created using Static Cells in IB/Storyboard. However, I need to hide some of the cells at runtime depending on certain conditions.

I have found a few 'answers; to this question on SO, e.g.

UITableView set to static cells. Is it possible to hide some of the cells programmatically?

.. and they focus on setting the height of the cell / row to 0. This is great, except I now get exceptions from AutoLayout because the constraints can't be satisfied. How do I get around this last problem? Can I temporarily disable Auto-Layout for a subview? Is there a better way to be doing this in iOS7?

like image 573
ConfusedNoob Avatar asked Sep 22 '13 03:09

ConfusedNoob


4 Answers

I found the best way to do this is to simply handle the numberOfRowsInSection, cellForRowAtIndexPath and heightForRowAtIndexPath to selectively drop certain rows. Here's a 'hardcoded' example for my scenario, you could do something a little smarter to intelligently remove certain cells rather than hard code it like this, but this was easiest for my simple scenario.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [super tableView:tableView cellForRowAtIndexPath:indexPath];
    if (indexPath.section == 0 && hideStuff) {
        cell = self.cellIWantToShow;
    }
    return cell;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    CGFloat height = [super tableView:tableView heightForRowAtIndexPath:indexPath];
    if (indexPath.section == 0 && hideStuff) {
        height = [super tableView:tableView heightForRowAtIndexPath:[NSIndexPath indexPathForRow:2 inSection:0]];
    }
    return height;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    NSInteger count = [super tableView:tableView numberOfRowsInSection:section];

    if (section == 0 && hideStuff) {
        count -= hiddenCells.count;
    }

    return count;
}
like image 67
ConfusedNoob Avatar answered Oct 20 '22 08:10

ConfusedNoob


Hide the cells on the storyboard and set the height to 0:

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    let cell: UITableViewCell = super.tableView(tableView, cellForRowAtIndexPath:indexPath)
    return cell.hidden ? 0 : super.tableView(tableView, heightForRowAtIndexPath:indexPath)
    }
}
like image 44
fede1608 Avatar answered Oct 20 '22 06:10

fede1608


If you ensure there's no constraint touching the bottom edge of the cell, autolayout shouldn't barf (tested on iOS 6.0, 6.1, 7.0). You'll still 'anchor' to the top edge and have to pin the heights. (You can do the reverse and anchor to the bottom, of course.)

If your layout depends on both the top and bottom edge positions, it may be possible to programmatically remove the constraints (they're just objects, after all).

like image 37
Ian Howson Avatar answered Oct 20 '22 07:10

Ian Howson


The simplest way is to change height of sections and rows. It works for me.

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    if (section == 3) {
        return 0;
    } else {
        return [super tableView:tableView heightForHeaderInSection:section];
    }
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [super tableView:tableView cellForRowAtIndexPath:indexPath];
    if (indexPath.section == 3) {
        cell.hidden = YES;
        return 0;
    } else {
        cell.hidden = NO;
        return [super tableView:tableView heightForRowAtIndexPath:indexPath];
    }
}
like image 24
otello Avatar answered Oct 20 '22 07:10

otello