28

In my cell.xib, I have a label, with constraints to all its sides. I've set that label to lines = 0 and line-break = word wrap. Then, I do this to my TableView:

self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 100.0

Everything works great, and my UITableViewCell is auto-height. If the text is long, then my tableView intelligently calculates the size.

The problem is -- how do I tell my UITableView to "re-calculate" the size once the content changes in the cell?

My cell could call its delegate, and in this delegate, I'd like the TableView to re-draw the height.

Right now, the content in my cells change constantly, but the cell height never changes.

Fahim Parkar
  • 30,974
  • 45
  • 160
  • 276
TIMEX
  • 259,804
  • 351
  • 777
  • 1,080
  • if your UITableview not resized with`UITableViewAutomaticDimension ` then it problem with Constraints. and another way to auto resize i sugest yopu to use **KeyValue Observer**. – Vvk Mar 16 '16 at 04:21
  • do you meant your tableview height will change as per the height of the cells? and the issue is cell height is changing but tableview height is not changing? – Fahim Parkar Mar 16 '16 at 05:06
  • Can you put the screenshot? And also do you want to increase the height of `UITableViewCell` or `UITableView`? Also, you can running on which iOS Version? – Sohil R. Memon Mar 16 '16 at 05:43
  • Also, why you are not using Prototype `UITableViewCell`? – Sohil R. Memon Mar 16 '16 at 05:43
  • TIMEX, not responding to anyone, he might just want to get all the possible ways of doing this. All the answer below should satisfy the question, there is not magic way to do this other than the answers below. – Bharat Modi Mar 16 '16 at 07:49
  • @TIMEX you can KVO for the `contentSize` of the `UITableView`, then update the `UITableView` `frame.height` – onmyway133 Mar 16 '16 at 09:36

9 Answers9

42

There is a documented way to do this. See UITableView.beginUpdates() documentation:

You can also use this method followed by the endUpdates method to animate the change in the row heights without reloading the cell.

So, the correct solution is:

tableView.beginUpdates()
tableView.endUpdates()

Also note that there is a feature that is not documented - you can add a completion handler for the update animation here, too:

tableView.beginUpdates()
CATransaction.setCompletionBlock {
   // this will be called when the update animation ends
}

tableView.endUpdates()

However, tread lightly, it's not documented (but it works because UITableView uses a CATransaction for the animation).

Sulthan
  • 128,090
  • 22
  • 218
  • 270
  • Thanks Sulthan. How can I update the height of only one cell? – TIMEX Mar 18 '16 at 00:16
  • 1
    @TIMEX This method makes the table to query the new heights and animate changes (sync with the data model). If you want to change height of only one cell, you will have to change only one height in your data model (e.g. change `label.text` only in one cell, not in several cells at once). – Sulthan Mar 18 '16 at 09:05
7

I've found the best way to get it to check heights is to call, after whatever text change has been made, in order:

self.tableView.beginUpdates()
self.tableView.endUpdates()

This causes the tableView to check heights for all visible cells and it will cause changes to be made as needed.

sschale
  • 5,168
  • 3
  • 29
  • 36
2

I think the simplest solution is to reload that specific cell. For example:

- (void)yourDelegateMethodOfCell:(UITableViewCell *)cell {
    NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
    //If cell is not visible then indexPath will be nil so,
    if (indexPath) {
        [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
    }
}
Muhammad Zeeshan
  • 2,441
  • 22
  • 33
2

You can get automatic cell height by this code

tableView.beginUpdates()
// add label text update code here 
// label.numberOfLines = label.numberOfLines == 0 ? 1 : 0
tableView.endUpdates()

Below is the reference to this solution with demo :

GitHub-RayFix-MultiLineDemo

Vinay Jain
  • 1,653
  • 20
  • 28
0

I got your point, and I met the problem before.
Your cell is in AutoLayout, and you wish the cell changes by itself. Here is recommended answer for that: Using Auto Layout in UITableView for dynamic cell layouts & variable row heights , so we don't talk about that again.

So here we focus on your problem.

Since the content of your cell changes constantly, which means the content has updated. Here we suppose the content is a label. We set the label's text, and surely the label's height maybe change.

Here comes the point: How does the label's change inform the cell to update?

We use AutoLayout, surely we have to update the constraint of height for the label.

And I think it will work!

Below is the detail step:
1. We setup the constraints for the cell's subviews.(I think it's done)
2. One of the label's height is changed by itself.(I think it's done too)
3. We get the new height of the label, and update the constraint of height for the label.(what we have to do)

Community
  • 1
  • 1
childrenOurFuture
  • 1,889
  • 2
  • 14
  • 23
0

Seems you wanted to reload the particular cell/cells based on content changes

Here we have a couple of options

1) Need to reload the entire table view .

or else

2) Reload particular cell/cells based on content changes.

But the preferred option would be reloading the particular cell,

Why because when you asked your UITableView instance to reload a couple of cells,tableview will asks its datasource(-tableView:cellForRowAtIndexPath:) to get the updated content,so that the reloaded cells will have the updated size & Updated content aswell.

Try to reload the cells when the content/height need to update based on content

Hope that helps! Happy coding :)

Naresh Reddy M
  • 1,096
  • 1
  • 10
  • 27
0

Take a look at this answer : Using Auto Layout in UITableView for dynamic cell layouts & variable row heights

How to achieve dynamic cell size is described very thorough there.

As a suggestion for testing try adding setNeedsLayout to:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

or

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath 
Community
  • 1
  • 1
Georgi Boyadzhiev
  • 1,351
  • 1
  • 13
  • 18
0

To disable the annoying tableView animation:

UIView.setAnimationsEnabled(false)
tableView.beginUpdates()
// cell.titleLabel?.text = "title"
// cell.detailTextLabel?.text = "Very long text ..."
// cell.detailTextLabel?.numberOfLines = 0
tableView.endUpdates()
UIView.setAnimationsEnabled(true)
fethica
  • 759
  • 6
  • 10
-1

You can resize your cell height by implementing below method only

 - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath{
return UITableViewAutomaticDimension;
}
Sachin Amrale
  • 277
  • 1
  • 9