简体   繁体   中英

Subview has no width or height after setting auto layout constraints

I'm trying to layout a child view controller's view within its parent view. The child view controller's view (the subview) must span the entire parent view, with the exception of a 14 pixel top margin.

It seems to me that the following code should be enough to accomplish this, but while the origin of the subview turns out correct (0, 14), its width and height are both 0.

I'm using the following code to add the child view controller and set its view constraints:

[self.view addSubview:_infoController.view];
[self addChildViewController:_infoController];
[_infoController didMoveToParentViewController:self];

UIView *infoView = _infoController.view;
NSDictionary *viewsDict = NSDictionaryOfVariableBindings(infoView);
NSArray *heightConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-14-[infoView]|" options:0 metrics:nil views:viewsDict];
NSArray *widthConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[infoView]|" options:0 metrics:nil views:viewsDict];

NSMutableArray *constraints = [NSMutableArray array];
[constraints addObject:[heightConstraints objectAtIndex:0]];
[constraints addObject:[widthConstraints objectAtIndex:0]];

[infoView setTranslatesAutoresizingMaskIntoConstraints:NO];

[self.view addConstraints:constraints];
[self.view setNeedsUpdateConstraints];

This results in a view with origin (0, 14) and size (0, 0).

Alternatively, when I don't disable the 'translatesAutoresizingMaskIntoConstraints' property the view does have a valid origin and size but then there is a constraint conflict and the 14px top margin is thrown away. The conflict shown is the following:

"<NSLayoutConstraint:0xba6bad0 V:|-(14)-[UIView:0xba6aec0]   (Names: '|':UIView:0xa3b9200 )>",
"<NSAutoresizingMaskLayoutConstraint:0xb8b4db0 h=--& v=--& V:[UIView:0xba6aec0(480)]>",
"<NSAutoresizingMaskLayoutConstraint:0xb8b4180 h=--& v=--& UIView:0xba6aec0.midY == + 240>"


Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0xba6bad0 V:|-(14)-[UIView:0xba6aec0]   (Names: '|':UIView:0xa3b9200 )>

Any ideas?

constraintsWithVisualFormat:options:metrics:views: returns a NSArray for a reason. That reason is that a visual format usually defines more than one constraint.

But you are throwing away all constraints except the first of each visual format. You just add the first constraint of each visual format to the view. Most likely you did not specify enough constraints to define the complete layout.

Your code should look like this

NSArray *heightConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-14-[infoView]|" options:0 metrics:nil views:viewsDict];
[self.view addConstraints:heightConstraints];
NSArray *widthConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[infoView]|" options:0 metrics:nil views:viewsDict];
[self.view addConstraints:widthConstraints];

You don't need the constraints array.

Try this instead:

[self.view addSubview:_infoController.view];
[self addChildViewController:_infoController];
[_infoController didMoveToParentViewController:self];

UIView *infoView = _infoController.view;
NSDictionary *viewsDict = NSDictionaryOfVariableBindings(infoView);
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-14-[infoView]|" options:0 metrics:nil views:viewsDict]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[infoView]|" options:0 metrics:nil views:viewsDict]];

[infoView setTranslatesAutoresizingMaskIntoConstraints:NO];

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM