59

I have the classical grouped UITableView with editable UITextViews inside every cell. This text views can be single or multi-lined, and I want the cell to increase its height as the user writes and the text starts a new line.

My question is: do I need to reload the whole table just to increase the height of a cell? Isn't there any other method?

I've been searching a lot, and previous answers and tutorials just talk about how to calculate text height, how to implement heightForRowAtIndexPath... things that I already know. My concern is that, to achieve what I want, I will have to calculate height and reload the table every time the user enters a new character, which I don't find very clean or efficient.

Thanks.

araid
  • 677
  • 1
  • 9
  • 9

4 Answers4

94
[tableView beginUpdates];
[tableView endUpdates];
Andrey Zverev
  • 4,409
  • 1
  • 28
  • 34
63

You do not always have to reload the entire table. You can instead just reload that one row.

[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:0 inSection:0]] withRowAnimation:UITableViewRowAnimationFade];
rickharrison
  • 4,867
  • 4
  • 35
  • 40
  • Thanks! But I have another problem now: I just want to reload that row to increase its size, I don't want the cell content to be instanced again. However, dequeueReusableCellWithIdentifier:@"customid" only starts reusing after second call. What could I do? – araid Jun 22 '10 at 11:55
  • @rickharrison actually you can, check out my answer below. – Andrey Zverev Oct 25 '12 at 08:16
  • It's doing the job really nice, but the cell's content grows respectively. How can I avoid this? – Gal Apr 23 '13 at 08:24
  • 3
    I'm having a big problem with this... I have a TextField in my cell and calling reload(anything) will cause my textfield to resign first responder status. Any ideas? – Daniel T. May 13 '13 at 14:53
  • 1
    Programmatically save your IndexPath of your row and set becomeFirstResponder to your TextField – Sn0wfreeze Sep 02 '14 at 20:58
  • probably best just to add beginUpdates and endUpdates since thats technically what you need to add as well – Daniel Galasko Aug 06 '15 at 07:28
  • @Sn0wfreeze thats not a good recommendation, you can get the indexPath of the cell from the textField alone http://stackoverflow.com/a/27938042/1652402 – Daniel Galasko Aug 06 '15 at 07:29
  • The similar solution is to call `moveRowAtIndexPath:toIndexPath:` for the same `indexPath` [(see details here)](http://stackoverflow.com/a/37623597/2066428) – malex Jun 03 '16 at 21:23
27

To be more specific, yes, you have to implement tableView:heightForRowAtIndexPath: to calculate the new height, then do as rickharrison says and call [tableView reloadRowsAtIndexPaths:withRowAnimation]. Lets say your cells can have an expanded height and a normal height, and you want them to grow when tapped on. You can do:

-(CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*) indexPath 
{
    if ([expandedPaths containsObject:indexPath]) {
        return 80;
    } else {
        return 44;
    }
 }

-(void)tableView:(UITableView*) didSelectRowAtIndexPath:(NSIndexPath*) indexPath
{
    [expandedPaths addObject:indexPath];
    [tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
Peter DeWeese
  • 18,141
  • 8
  • 79
  • 101
Elfred
  • 3,851
  • 22
  • 16
4

-reloadRowsAtIndexPaths:withRowAnimation did not resize the UITableViewCell height, even after I changed the Cell's frame. It only worked when I followed it with a -reloadData:

[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:0 inSection:0]] withRowAnimation:UITableViewRowAnimationFade];
[tableView reloadData];
windson
  • 667
  • 8
  • 16
  • Maybe you were referencing the wrong indexPath, if you debug the application you clearly see that after you call tableView reloadRowsAtIndexPath: the method tableView:heightForRowAtIndexPath is in fact called. – Pedro Borges Apr 08 '15 at 22:58