Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS 8 autolayout, VFL and margin equals or greater than

I'm experiencing problems with constraints in VFL on iOS 8, while on 6 and 7 it is all OK. This is the constraint:

H:|-margin-[_imageView]-(=>margin)-[_label]-margin-|

Both _imageView_and _label get their correct intrinsic width, and the margin grows as expected. I want to achieve

|-[_imageView]-------------------------------[some text]-|

|-[_imageView]---------------------------[a larger text]-|

|-[_imageView]-----------------------[a very large text]-|

|-[_imageView]-[a very very very very very very larg...]-|

It is OK visually but it raises a broken constraint exception:

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x7b856ee0 H:[UIImageView:0x7b8ef1f0]-(>=12)-[UILabel:0x7b8e7c60'Test']>

There is no ambiguity after printing _autolayoutTrace.

However, if the constraint involves only labels there is no problem at all:

H:|-margin-[_label1]-(=>margin)-[_label2]-margin-|

The problem could be solved following the next steps:

Changing the constraint removing >= and adding priorities:

H:|-margin-[_imageView]-(margin@750)-[_label]-margin-|

Setting the hugging priority of the _imageView

[_imageView setContentHuggingPriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisHorizontal];

Setting the compression resistance of the _label

[_label setContentCompressionResistancePriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisHorizontal];

With these rules there is no problem on any platform. Is all of this necessary on iOS 8? Is it a bug or I was doing it wrong?

Thanks.

like image 922
emenegro Avatar asked Sep 11 '14 11:09

emenegro


1 Answers

I've started project from scratch and here is my code (which actually works fine):

UIView *topView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 200)];
topView.backgroundColor = [UIColor redColor];
topView.translatesAutoresizingMaskIntoConstraints = NO;

UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(20, 20, 40, 160)];
imageView.backgroundColor = [UIColor greenColor];
imageView.translatesAutoresizingMaskIntoConstraints = NO;
[topView addSubview:imageView];

self.label = [[UILabel alloc] initWithFrame:CGRectMake(80, 80, 200, 32)];
self.label.backgroundColor = [UIColor yellowColor];
self.label.text = @"some text";
self.label.translatesAutoresizingMaskIntoConstraints = NO;
[topView addSubview:self.label];


self.tableView.tableHeaderView = topView;

NSDictionary *views = @{@"imageView":imageView, @"label":self.label};

NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-margin-[imageView(40)]-(>=margin)-[label]-margin-|" options:0 metrics:@{@"margin": @30} views:views];
NSArray *imageConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-20-[imageView(160)]-20-|" options:0 metrics:nil views:views];
NSArray *textConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-40-[label]" options:0 metrics:nil views:views];
NSArray *topConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:[topView(320)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(topView)];

[topView addConstraints:constraints];
[topView addConstraints:imageConstraints];
[topView addConstraints:textConstraints];
[topView addConstraints:topConstraints];

I think your main problem is that you don't turn off translatesAutoresizingMaskIntoConstraints which produces UIView-Encapsulated-Layout (which I've never met prior to iOs8). I haven't found a place where it is good documented, but there are numbers of question regarding that constraint.

I've also created github repo, so you can try it yourself: https://github.com/Nikita2k/constraintsTest

Additionally, you can take a look at WWDC2014 video - What's new in Table and Collection Views (~20min). There are some info, that you can see UIView-Encapsulated-Layout problem now, but it will be fixed later. Also, you can try playing with rowHeight as all ios8 tableViews from storyboard (or xib) should explicitly set

self.tableView.rowHeight = UITableViewAutomaticDimension

I'm not sure, will it help in this particullar case or not, but give it a try too!

like image 187
Nikita Took Avatar answered Sep 20 '22 02:09

Nikita Took