I’m working on an application where I have a custom subclass of UITableViewCell. I want to make the cell’s height dynamic based on the text inside it. I try do do that in my heightForRowAtIndexPath method. But I’m having some issues, the following code causes and EXC_BAD_ACCESS(code=2 address=0xb7ffffcc) error.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
PostCell *cell = (PostCell *)[tableView cellForRowAtIndexPath:indexPath];
CGSize postTextSize;
if (![cell.postText.text isEqualToString:@""]) {
postTextSize = [cell.postText.text sizeWithFont:[UIFont systemFontOfSize:14] constrainedToSize:CGSizeMake(cell.postText.frame.size.width, 200)];
} else {
postTextSize = CGSizeMake(cell.postText.frame.size.width, 40);
}
return postTextSize.height + cell.userName.frame.size.height + 10;
}
If I instead have:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 100;
}
It works.
It seems to be crashing on this line: PostCell *cell = (PostCell *)[tableView cellForRowAtIndexPath:indexPath];, and I don’t know why. I have tried to build clean and reset the simulator, but neither worked. Any ideas why this is happening?
I have tried to reproduce the problem. It turns out that calling
cellForRowAtIndexPath:insideheightForRowAtIndexPathcausesheightForRowAtIndexPathto be called recursively. Here is an extract of the stack backtrace after the 3 recursion steps:Finally the program crashes. On my Simulator this happens when the back trace is about 57000 levels deep.
Old answer (not wrong, but does not explain the
EXC_BAD_ACCESS):
The problem is that
returns
nilfor rows that are currently not visible. A table view allocates only so many cells that are required to display the currently visible rows. The cells are reused when you scroll the table view.But
heightForRowAtIndexPathis called for all cells of the table view before any row is displayed.As a consequence, you should not get the text from the table view cells to compute the height in
heightForRowAtIndexPath. You should get the text from your data source instead.