I am trying to use AutoLayout to configure the subviews in my table view cells and in the ideal case would like the table view cell to be just as high as necessary to contain all the subviews. However, that does not seems to be possible, since the height for a cell is determined before the cell is actually created.
So, for now, I just looked at the constraints I set up and calculated the total height needed to contain everything and set that in the storyboard as the row height for this specific TableViewCell prototype cell and I also return this height in the tableView:heightForRowAtIndexPath:
method.
Now, my table view cell looks like this (screenshot from storyboard):
There are two constraints which don't have a size shown, they both have the size 10 (the button-top-container-view and the distance between the slider and the label in the middle).
Going from top-to-bottom the following distance occur:
- 10 (distance)
- 50 (height of button)
- 20 (distance)
- 20 (height of label)
- 10 (distance)
- 30 (height of slider)
- 20 (distance)
leading to a total height of 160.
That's exactly what I have set in the inspector of this cell:
but as you can see from the first screenshot, Interface builder complains that the constraints are conflicting (that's why they are displayed in red). IB is satisfied if I set the height to 161, but that is wrong.
Also, if I do, I get exceptions at runtime due to conflicting constraints:
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)
(
"<NSLayoutConstraint:0x8d80240 V:[UISlider:0x8d81190(30)]>",
"<NSLayoutConstraint:0x8d833e0 V:[UILabel:0x8d83300(20)]>",
"<NSLayoutConstraint:0x8d83750 V:[UIButton:0x8d83600(50)]>",
"<NSLayoutConstraint:0x8d85050 V:|-(10)-[UIButton:0x8d83600] (Names: '|':UITableViewCellContentView:0x8d80ef0 )>",
"<NSLayoutConstraint:0x8d851d0 V:[UILabel:0x8d83300]-(10)-[UISlider:0x8d81190]>",
"<NSLayoutConstraint:0x8d85200 V:[UISlider:0x8d81190]-(20)-| (Names: '|':UITableViewCellContentView:0x8d80ef0 )>",
"<NSLayoutConstraint:0x8d85320 V:[UIButton:0x8d83600]-(20)-[UILabel:0x8d83300]>",
"<NSAutoresizingMaskLayoutConstraint:0x8d8b7a0 h=--& v=--& V:[UITableViewCellContentView:0x8d80ef0(161)]>"
)
the last one is the only one I did not explicitly set, but it seems to be generated from the row-height setting in the storyboard, since my tableView:heightForRowAtIndexPath:
method returns 160:
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == self.fetchedItemSetsController.fetchedObjects.count - 1)
{
return 160;
}
return 44;
}
(at the moment I always want the last cell to be the large and special one)
So, okay, IB complains when I set the row height to 160, but when I set it to 161 the runtime complains. So I tried ignoring IB and set the row height to 160 in the storyboard as well (as seen in the second screenshot). In that case, I get the same error message with a tiny difference:
"<NSLayoutConstraint:0x17809ce80 V:[UISlider:0x125613660(30)]>",
"<NSLayoutConstraint:0x1782814f0 V:[UILabel:0x125615100(20)]>",
"<NSLayoutConstraint:0x178281a90 V:[UIButton:0x125615b50(50)]>",
"<NSLayoutConstraint:0x178281b80 V:|-(10)-[UIButton:0x125615240] (Names: '|':UITableViewCellContentView:0x178161980 )>",
"<NSLayoutConstraint:0x178281c20 UIButton:0x1256157b0.height == UIButton:0x125615240.height>",
"<NSLayoutConstraint:0x178281d10 UIButton:0x1256157b0.height == UIButton:0x125615980.height>",
"<NSLayoutConstraint:0x178281e00 V:[UILabel:0x125615100]-(10)-[UISlider:0x125613660]>",
"<NSLayoutConstraint:0x178281e50 V:[UISlider:0x125613660]-(20)-| (Names: '|':UITableViewCellContentView:0x178161980 )>",
"<NSLayoutConstraint:0x178281f40 UIButton:0x125615980.height == UIButton:0x125615b50.height>",
"<NSLayoutConstraint:0x178282030 V:[UIButton:0x125615240]-(20)-[UILabel:0x125615100]>",
"<NSAutoresizingMaskLayoutConstraint:0x178283340 h=--& v=--& V:[UITableViewCellContentView:0x178161980(159.5)]>"
The constraint for the height of the table view cell is now 159.5 instead of 160. I also encountered it as 160.5 before, with the same storyboard setting, but I am not sure where that came from.
So, first I thought it was just a display bug in IB, but now it actually seems to be creating the wrong constraint. It creates a constraint with 160.5 (or 159.5) instead of the 160 I specified. Why is that? What can I do about it?
Btw: The cells seems to be displayed correctly, but then again I doubt I would be able to see a 0.5 point difference. Mainly, I would like to get rid of the exceptions, since they make the debugging much harder, but I would also like to know what is going on here.
UPDATE:
The 159.5 is not JUST due to the storyboard setting I just noticed, it is a strange combination of the storyboard setting and the return value of the tableView:heightForRowAtIndexPath:
.
Here are a few examples of the height of the generated autoresizingmasklayoutconstraint depending on the storyboard height (sb) setting and the return value of the tableView:heightForRowAtIndexPath:
method (method). In all cases, the constraints of the subview should lead to a height of 160 and are not changed.
- 160 (sb) & 160 (method): 159.5 (constraint)
- 161 (sb) & 160 (method): 159.5 (constraint)
- 160 (sb) & 161 (method): 160.5 (constraint)
- 162 (sb) & 161 (method): 162 (constraint)
- 161 (sb) & 162 (method): 161 (constraint)
- 162 (sb) & 162 (method): 162 (constraint)
So I thought, okay, for (6.) they all agree, I will just make the label's height 22, so the total height according to the subviews will be 162 as well. Result:
6a. 162 (sb) & 162 (method), 162 (total height of subviews): 161.5 (constraint)
WHAT?!
Any ideas what's happening here?
Update 2 I provided an example project that reproduces the issue on Github.