0

I have UITableViewController with static grouped cells. In a particular view, I want to remove some of the cells. If I just hide them, it leaves an empty space, so I want to set the cell's rowHeight to 0 instead. I'm having trouble doing this because I can't seem to get the indexPath of the cell I want to hide. I have a reference to it via IB connection. After reading around, it seems the best way to do this is via the heightForRowAtIndexPath method. Here is my code:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSIndexPath *myIndexPath = [self.tableView indexPathForRowAtPoint:self.billToPostalCell.center]; 
    //crashes here

    if ([indexPath isEqual:myIndexPath]) {
        return 0; 
    }
    return 44;
}

Before this, I was trying IndexPathForCell, but also would crash. From what I read, heightForRowAtIndexPath should work, even when the cells aren't visible. When it crashes, nothing shows up in the debugger either.

Undo
  • 25,519
  • 37
  • 106
  • 129
abc123
  • 8,043
  • 7
  • 49
  • 80

3 Answers3

3

What you are doing is causing infinite recursion leading to a ... wait for it ... stack overflow!

Inside the heightForRowAtIndexPath: method you can't ask the table for a cell or the indexPath for a row because those methods need to know the cell's height. So those call result in heightForRowAtIndexPath: being called. And since you then call the same offending methods again, this goes on until things go boom.

Since your goal is to hide the cells, you should remove the cells from the table using the proper UITableView method (deleteRowsAtIndexPaths:withRowAnimation:). Of course you need to update your data model first (to remove the rows).

rmaddy
  • 314,917
  • 42
  • 532
  • 579
  • Thanks, how exactly do I update the data model first? These are static cells with IB connected UITextFields and UILabels in them which are populated individually in `viewWillAppear` method. Just calling the `deleteRowsAtIndexPaths:withRowAnimation` method throws this error: _'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 4_. From Googling, I know I need to update the data source model as you said. – abc123 Apr 22 '13 at 23:53
  • Your 'numberOfRowsForSection` method should return a number based on some data model you have (not hardcoded to some specific value). It is that data model you need to update. This is usually some sort of array. Remove the object from the array first, then tell the table to delete the row. – rmaddy Apr 23 '13 at 00:23
  • That's the thing. In this case, there is no array. The tableView's dataSource delegate is not connected the view controller. And I don't implement any of the dataSource delegate's methods. Each cell drawn in IB has a textField connected to code via IB outlet. Then in the code, I populate the textFields like this: `self.myTextField.text = self.customer.someString`. I tried setting the cell to nil, before deleting the row, but no dice. – abc123 Apr 23 '13 at 00:35
  • I found this answer which helped me on my follow up questions. http://stackoverflow.com/a/9434849/1672161 Thanks for answering my original question. – abc123 Apr 23 '13 at 04:51
2

You shouldn't be changing the cells visibility and height. If you want to remove the cells and add them back later, or never add them back you should be using the insert and delete methods on the UITableView. Here is a good starting point documentation.

Additionally, you shouldn't use methods on the tableView from within tableView:heightForRowAtIndexPath: like indexPathForRowAtPoint: as the tableView has to work out its own height before it can calculate things like this. You are probably getting an error because you are in a infinite loop.

Michael Reneer
  • 2,271
  • 1
  • 16
  • 22
0

Use -deleteRowsAtIndexPaths:withRowAnimation to delete rows. Never manipulate the visibility of a cell as a substitute for removing it; that can lead to serious memory issues and is just general bad practice. Just pass in an NSArray filled with the NSIndexPath of the row you'd like to remove.

You mentioned that the indexPathForRowAtPoint: method wasn't working. This is almost surely a problem with the point you're passing in to it. Be sure to log out the value of billToPostalCell.center to be sure you're passing in a legitimate value. However, there really isn't a need to do this if you're dealing with static cells, as you should already know the index path (at least for the initial cell removal).

As others have mentioned, the documentation on removing cells provides all the additional information you should need.

The Kraken
  • 3,158
  • 5
  • 30
  • 67