My main scene shows a child UIViewController
, by putting a Child Container in its View, and embedding a child UIViewController in that Child Container. I do that by ctrl-dragging from the Child Container to the child UIViewController
in the storyboard
, and choosing the "embed" segue.
That lets me encapsulate and reuse the child UIViewController
elsewhere. I think that is fairly standard. But I can't get it to auto layout properly.
I've made a simple test case to demonstrate this: https://github.com/murraycu/ios-example-autolayout-of-child-container-views
It has two UIViewControllers
that are embedded in a Tab Controller so you can switch between them.
The "Simple" tab shows the SimpleViewController
, which shows an image and a label, seen here in the storyboard:
Neither the UIImage or the UILabel has a height constraint specified, though they have an Equal Width (equal to the parent view) constraint to keep the widths simple.
That UILabel is clearly not very high but the UIImage and UILabel have slightly different Content Hugging priorities, making their heights not ambiguous according to Auto Layout. So thanks to auto layout, when I set its text at runtime to some text that would require more space, it takes up more space, taking space away from the UIImage above it. That's good - it is the behaviour that I want, as seen in the emulator:
Now to the problem: The "With Child Container" tab shows the WithChildContainerViewController, which shows the same image but shows my ChildViewController (embedded in a Child Container) instead of the UILabel. And that embedded ChildViewController shows the UILabel. Here it is in the storyboard:
However, the auto layout system now doesn't seem to know how much space the Child Container needs to show all the text in the label in my ChildViewController. As in the "Simple" tab, neither the UIImage or the Child Container has a height constraint specified. Now XCode complains that "Height is ambiguous for "container view". And it looks like this in the simulator:
That's improved if I add a constraint to the Child Container, constraining its bottom to the bottom of the parent view, as suggested by @iphonic: https://github.com/murraycu/ios-example-autolayout-of-child-container-views/commit/1d295fe0a6c4502764f8725d3b99adf8dab6b9ae but the height is still wrong:
How can I let the auto layout system know what to do? I've thought about implementing UIView's intrinsicContentSize, but UIViewController isn't a UIView.
Suggestion is, do it programatically rather than via IB. See below
_childController=[self.storyboard instantiateViewControllerWithIdentifier:@"ChildController"];
[self addChildViewController:_childController];
[_container addSubview:_childController.view];
[_childController didMoveToParentViewController:self];
_childController.view.frame=_container.bounds;
//add constraints
UIView *subView=_childController.view;
UIView *parent=_container;
subView.translatesAutoresizingMaskIntoConstraints=NO;
NSLayoutConstraint *width =[NSLayoutConstraint
constraintWithItem:subView
attribute:NSLayoutAttributeWidth
relatedBy:0
toItem:parent
attribute:NSLayoutAttributeWidth
multiplier:1.0
constant:0];
NSLayoutConstraint *height =[NSLayoutConstraint
constraintWithItem:subView
attribute:NSLayoutAttributeHeight
relatedBy:0
toItem:parent
attribute:NSLayoutAttributeHeight
multiplier:1.0
constant:0];
NSLayoutConstraint *top = [NSLayoutConstraint
constraintWithItem:subView
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:parent
attribute:NSLayoutAttributeTop
multiplier:1.0f
constant:0.f];
NSLayoutConstraint *leading = [NSLayoutConstraint
constraintWithItem:subView
attribute:NSLayoutAttributeLeading
relatedBy:NSLayoutRelationEqual
toItem:parent
attribute:NSLayoutAttributeLeading
multiplier:1.0f
constant:0.f];
[parent addConstraint:width];
[parent addConstraint:height];
[parent addConstraint:top];
[parent addConstraint:leading];
Hope it helps.
Cheers.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With