IOS8 changes the height of the dynamic cell "now", the internal contents of the cell

Here is the dynamic cell

enter image description here

Note. In the example, the text is not data driven. This is just text local to the cell (consider, say, help text). At run time, change the .text UILabel from one word to many lines, using the button actually located inside the cell. iOS resizes cells and tables ....

... but only if the cell scrolls overs and then again .

How to warn the appearance of a table in order to recount everything "now"?


(Please note this question is ONLY in the case of iOS8 +, Xcode7 +, auto-detection for dynamic cell heights.)

+5
source share
5 answers

I assume that you are not setting the text UILabel property inside cellForRowAtIndexPath , but rather in a different place (or executing it asynchronously). If this happens, I would not update the interface. Rather, I updated the model that supports the table, and then called reloadRowsAtIndexPaths . This will allow calling the cellForRowAtIndexPath call cellForRowAtIndexPath , but unlike reloading the entire table, it will gracefully keep the contentOffset in the view table, where it is.

I know that all this sounds unnecessarily complicated, but the point is that you do not have this idea, it looks in the table. He has to do all kinds of things besides updating the cell. Ie, if the cell was growing, find out which cells scroll from the field of view and deactivate them. If the cell shrinks, find out which cells scroll as a result of the result.

This is an amazingly complex dance. You can try calling setNeedsLayout in a cell, but I did not expect this to work (and even if that happens, this is a fragile approach). The table view is responsible for managing its cells, so if you really need to just update the model and reload this cell.

+1
source

Height change

Basically, there are two ways:

The first is to actually reload the cell (not the table). Rebooting will cause a new heightForRow (don't forget to clear the cache if you cache sizes), which will return the correct new height:

  let indexPaths = [NSIndexPath(forRow: ~the rows in question~, inSection: 0)] self.table.reloadRowsAtIndexPaths(indexPaths, withRowAnimation: .Automatic) 

(Note that this often requires reloading more than one row, especially if you select / deselect, you need to reload all rows.)

If, however, you ONLY want to change the cell size and the content as such, and you have not actually changed the contents of the data ... for example:

  • you clicked a button and you assigned a new local text in the output box (possibly help text):

  • You only changed the LAYOUT cells. for example, you made the font larger or changed the text block field so that the height of the text block changed, so the height of the whole cell changed:

In this case, instead of reloading, just call the following, which causes the tableview to basically do all the animations, and for this it needs new heights, so it asks:

  self.table.beginUpdates() self.table.endUpdates() 

True decision

I understand what the problem is. You are trying to change the cell height from the actual cell, but you will not succeed β†’ and you should not do this. Look, a cell is a view, and a view should not have any idea of ​​its data - a view is what it represents. If you need any changes, you should inform your controller about this. You can use notifications for this, but preferably protocols / delegates.

So, first you create a protocol in your cell that will be used to inform the controller that there is a change:

  protocol MyCellDelegate { func buttonTappedForCell(cell : UITableViewCell) } 

Now you need to match this protocol in your view controller, which contains the table:

  class MyClassWithTableView : MyCellDelegate 

Finally, you need to declare a delegate in the cell:

  class MyCell { var delegate : MyCellDelegate } 

And assign it in the cell configuration, which you probably have in the view controller:

  cell.delegate = self 

This is the basic setting for all delegates / protocols, and now, when you click on your button, you can redirect the action to your controller:

  @IBAction myButtonTouchUpInside() { self.delegate.buttonTappedForCell(self) } 

When doing all this, proceed as in Part 1. That is, a pair of reloadRowsAtIndexPaths or beginUpdates / endUpdates , as described above.

Hope this helps!

+2
source

Have you tried calling reloadRowsAtIndexPaths at the cell index? it should animate the new size if the restrictions are set correctly.

+1
source

You should call self.tableView.reloadData() only AFTER , after which you changed the text of the cell label.

This will make tableView redraw the cell. What happened when you scroll, the cell is reused , and redraws when it returns again.

EDIT:

If you cannot or will not do reloadData in your tableView, you can use:

 self.tableView.beginUpdates() self.tableView.reloadRowsAtIndexPaths([NSIndexPath(row:0 section:0)] withRowAnimation:UITableViewRowAnimation.Automatic) self.tableView.endUpdates() 
+1
source

I don't know your code, but have you really implemented your changes in the main thread. The same problem arose with me and was solved with putting exectuion in the main thread.

 dispatch_async(dispatch_get_main_queue()) { () -> Void in [...] } 
0
source

All Articles