1

I've seen a lot of guides about self-sizing cells in iOS 7 and 8. Unfortunately, all of them shows very simple cases (I mean two UILabel's with same width and which placed like the first under the second and their constraints are very simple too). So I've a situation that seems to be not so much difficult but I can't resolve a problem. I believe that it is very easy for the most of people and hope that somebody can help. The problem is that there is UITableViewCell with 3 child views inside. Every view is UILabel. Labels placed in such order: two labels at the top of UITableViewCell with fixed size and one at the bottom with fixed width but with dynamic height. How should I setup my constraints properly to make my UITableViewCell be self-sizing? This is how my cell must look like

ArnonZ
  • 3,822
  • 4
  • 32
  • 42
vendettacore
  • 1,439
  • 1
  • 13
  • 28

1 Answers1

2

The key to self-sizing is a vertical set of constraints that will determine the cell height. This isn't that complex, as you don't have two horizontal labels that vary in height.

Since headerLabel and dateLabel height don't vary, you only need to constrain the dynamicLabel to one of the two top labels.

In this example, we'll arbitrarily pick headerLabel to use in the vertical constraints. The spacing between the labels wasn't specified, so I'll assume it's 10. Adjust as necessary.

For your horizontal constraints, set leading and trailing space to the superview.

Your vertical constraints would simply look like "V:|-10-[headerLabel]-10-[dynamicLabel]-10-|" (and should

dynamicLabel will grow as tall as it needs, provided you set its numberOfLines to 0, and its height will end up determining the height of the cell.

Assuming the constraints are setup properly, and the storyboard cell height exactly matches the vertical height set by the constraints, you shouldn't see any storyboard warnings or errors, and should be good to go.

8.4 does address a number of issues, so you shouldn't require any specific (layoutSubViews/preferredMaxLayoutWidth/reloadData) code to work around earlier 8.x problems.

As an aside, a general tip is to pin your constraints to the superview margin, instead of the superView. This means your leading, trailing, top, and bottom constraints could be 2, instead of 10, since the margin is generally 8. This lets your white space adapt to different devices, which is a really nice touch.

  • Thanks for your answer. I'll try to do all step by step but I've a question. You said that vertical constraint must be "V:|-10-[headerLabel]-10-[dynamicLabel]-10-|" but my `dynamicLabel` must always be at bottom of the cell and if between `headerLabel` and `dynamicLabel` will be 10pt will it be always correct? – vendettacore Aug 31 '15 at 18:53
  • Yes. The `dynamicLabel` will always be at the "bottom" of the cell, because its bottom margin is 10. Regardless of the amount of whitespace you may want between the top and bottom labels -- increase the value as desired to achieve the look you want -- it should remain a constant. The only "non-constant" will be the height of the dynamic label, and Auto Layout will calculate that for you. So, self-sized cell height = 10 + headingHeight + 10 (inter-label spacing) + n (variable dynamic label height, calculated by Auto Layout) + 10. –  Aug 31 '15 at 18:59
  • Thank you very much!) works like a charm but there is a knonwn bug and by some reason not every cell sized properly when tableview shown first time. I tried to do `[self.tableView reloaddata];` forced in `-viewDidAppear` but it didn't help – vendettacore Sep 01 '15 at 06:44
  • When the initial layout is incorrect, it's generally because the cell width does not initially match the tableView width, which causes the labels to initially be laid out wrong. If everything is ok after scrolling cells off the screen, then back on, your constraints are correct. [You can work around the initial layout problem by setting the cell's width.](http://stackoverflow.com/a/32063950/4151918) –  Sep 01 '15 at 10:31