Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Autolayout sizes UITableViewCells incorrectly until reloadData is called

I have a tableview cell whose view is loaded from an nib and whose subviews are constrained using AutoLayout. I'm using the self-sizing cells feature of iOS 8. On first display, the cells look like this:

Too much margin.

The margin between the green view and the blue & gray views is larger than I expect. If I scroll down the view so more cells are created, or if I call reloadData on the tableview, then I get the correct result:

Just right.

It is as if the cells subviews are not correctly sized until the 2nd layout pass. How can I get around this? I've seen some posts that suggest setting setPreferredMaxLayoutWidth in layoutSubviews, like so:

-(void)layoutSubviews
{
    [super layoutSubviews];
    [self.redLabel setPreferredMaxLayoutWidth:[self.titleLabel bounds].size.width];
    [self.greenLabel setPreferredMaxLayoutWidth:[self.extendedLabel bounds].size.width];
    [self.blueLabel setPreferredMaxLayoutWidth:[self.dateLabel bounds].size.width];
    [self.grayLabel setPreferredMaxLayoutWidth:[self.tagsLabel bounds].size.width];
    [super layoutSubviews];
}

...but it seems to have no effect.

There doesn't appear to be any ambiguity in my constraints, but since they are set up in a .nib I'm not sure how to post them here.


Edit 1:

So I have the top space of the blue/gray views set to be >= the bottom of the green view, +3. Which is in effect what I get, since the space is greater.

However, if I set the relationship to be ==, I get a different visual error, where the red label is incorrectly sized for the amount of text it contains: enter image description here


Edit 2:

Not sure if I should start a new question, but it's the same problem.

Still having recurring problems with the layout as in Edit 1. Apart from the visual problem, it causes a horrible effect when a single cell changes in my tableview. The whole list will appear to collapse and reload. Additionally, I get the following autolayout error logged:

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:0x797c5bc0 UITableViewCellContentView:0x7970adc0.(null) == UILabel:0x79707cf0.trailing + 6>",
    "<NSLayoutConstraint:0x7977b560 UILabel:0x79707cf0.leading == UITableViewCellContentView:0x7970adc0.(null) + 6>",
    "<NSLayoutConstraint:0x7970a700 UITableViewCellContentView:0x7970adc0.width ==>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x797c5bc0 UITableViewCellContentView:0x7970adc0.(null) == UILabel:0x79707cf0.trailing + 6>

Where the UILabel referred to is the longer, green label. It seems like it can't reconcile the leading and trailing constraints with whatever width the cell has, as if the cell is smaller than 12 points overall. Logging out the width seems to always result in 320, however.

like image 366
blork Avatar asked Sep 21 '14 20:09

blork


1 Answers

Just to add, since most people have suggested things that did not work for me, here is how I fixed it (for iOS 8). I use XIB's for cells, but this should be universal.

First of all, there is a bug on UILabel where "-(void)layoutSubviews" is not being called so you can't really get the iOS 7.0 solution to work for iOS 8. Therefore, I use automatic cell resizing for iOS 8.

However, the bug described above was happening. I had to reload table view for cells to be correct. If you look at tutorials and examples out there, there are a bunch out there that work fine, while others complain that there's bugs. I was looking for the common denominator between buggy examples and correct ones, and the bug was: size-classes.

Instead of using "compact-width" and "any-height" use "any-any." Using "any-any" fixed all of the issues and everything works as expected. Sounds ridiculous, but try it!

like image 126
kgaidis Avatar answered Sep 19 '22 11:09

kgaidis