-1

Following https://stackoverflow.com/a/7313410/1971013 I need to get the height of each of my cells in - (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath.

But when I do:

- (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath
{
    MyTableViewCell* cell = (MyTableViewCell*)[self.tableView cellForRowAtIndexPath:indexPath];

    return cell.height;
}

this (of course) results in unwanted recursion blowing up my app.

Any ideas of how I should do this?

Community
  • 1
  • 1
meaning-matters
  • 21,929
  • 10
  • 82
  • 142
  • 2
    Using `heightForRowAtIndexPath` you define the height of a cell, but you are trying to return the default height of a cell that is `44`, instead I would suggest you put some condition and return some actual values.. – iphonic Aug 21 '14 at 18:28
  • 2
    Think of it this way - you don't ask a cell its height, you tell a cell its height. That's what the `heightForRowAtIndexPath` method is for - to tell the cell what its height is. – rmaddy Aug 21 '14 at 18:56
  • @maddy I know, but in my case the cells know how height they need to be to show their content. – meaning-matters Aug 21 '14 at 21:09

3 Answers3

1

The best answer is, sadly, I don't know. That's up to you here. The heightForRowAtIndexPath from UITableViewDelegate is what the UITableView uses to ask you what the height should be. In this function you are determining that.

Perhaps you can save it in your own memory in cellForRowAtIndexPath after you dequeueReusableCellWithIdentifier.

But if your linked questions are any indication, you're trying to expand a selected cell, correct? You can determine if it's the selected cell via

if ([indexPath compare:[tableView indexPathForSelectedRow]] == NSOrderedSame)
    return 88; // some expanded value
else
    return 44; // the default value
Gutblender
  • 1,340
  • 1
  • 12
  • 25
  • That won't work - the table view wants to know the height of every cell, not just the instantiated ones. – Colin Aug 21 '14 at 18:42
  • That's my point--`heightForRowAtIndexPath` is called for every (potential) cell before any are drawn via `cellForRowAtIndexPath`. – Gutblender Aug 21 '14 at 18:46
1

Gutblender is right: in the usual case, you don't ask a cell its height, you tell it.

It's important to embrace the fact that cells are recycled. From a practical perspective, you can't examine cells that are off screen because they don't exist.

Cautions aside, here are the options:

  1. Create a method that defines the height of your table view cells, and use that method to calculate the value you return from heightForRowAtIndexPath. You can then call that method from elsewhere to determine what the height of the cell will be at a given index path, whether or not it exists. This is the standard approach. It's also, 99.9% of the time, the correct one.

  2. Iterate through the table view's subviews. A bad idea because you don't control the NSTableView class, and the view hierarchy can change. And, again: cells are recycled.

  3. Create custom table view cell class, use something like the MVVM design pattern and let your model objects vend the table view cells. You won't have to worry about the view hierarchy, but again: cells are recycled – you will end up managing stale or incorrect state.

nzeltzer
  • 521
  • 4
  • 9
0

One method I've used on static table view's that don't have any reuse and the cells are pre-generated, is create a subclassed tableView cell with a height property, so in heightForRowAtIndexPath you can get the cell for that indexPath and return the cell's height you hard-coded in that you wanted for the cell. That way, any time you want to change the height you can change it directly on the cell itself and when you reloadData it should update the cell height.

Mike
  • 9,765
  • 5
  • 34
  • 59