I have two view controllers, parent and child.
So in the viewDidLoad
method I do the following:
ChildViewController* childViewController = [[ChildViewController alloc] init];
[self addChildViewController:childViewController];
// ChildViewController sets his own constraints in viewDidLoad
[self.view addSubview:childViewController.view];
[childViewController didMoveToParentViewController:self];
//
// setup constraints to expand childViewController.view to
// fill the size of parent view controller
//
So basically what happens is that updateViewConstraints
is called on ChildViewController before parent controller constraints apply, so in fact self.view.frame == CGRectZero
, exactly the same as I specified in custom loadView
method in ChildViewController
.
translatesAutoresizingMaskIntoConstraints
all set to NO
for all views.
What's the proper way to setup constraints in this case so ChildViewController
updates his constraints after parent?
Current log from both controllers is pretty frustrating, I do not understand how updateViewConstraints can be called before viewWillLayoutSubviews:
App[47933:c07] ChildViewController::updateViewConstraints. RECT: {{0, 0}, {0, 0}}
App[47933:c07] ParentViewController::updateViewConstraints
App[47933:c07] ChildViewController:viewWillLayoutSubviews. RECT: {{0, 0}, {984, 454}}
App[47933:c07] ChildViewController:viewDidLayoutSubviews. RECT: {{0, 0}, {984, 454}}
You can add constraints right after invoke of addSubview: , don't forget to set translatesAutoresizingMaskIntoConstraints
to false
Here is a code snippet of adding and hiding child view controller with constraints (inspired by apple guide)
Display
private func display(contentController content : UIViewController)
{
self.addChildViewController(content)
content.view.translatesAutoresizingMaskIntoConstraints = false
self.containerView.addSubview(content.view)
content.didMove(toParentViewController: self)
containerView.addConstraints([
NSLayoutConstraint(item: content.view, attribute: .top, relatedBy: .equal, toItem: containerView, attribute: .top, multiplier: 1, constant: 0),
NSLayoutConstraint(item: content.view, attribute: .bottom, relatedBy: .equal, toItem: containerView, attribute: .bottom, multiplier: 1, constant: 0),
NSLayoutConstraint(item: content.view, attribute: .leading, relatedBy: .equal, toItem: containerView, attribute: .leading, multiplier: 1, constant: 0),
NSLayoutConstraint(item: content.view, attribute: .trailing, relatedBy: .equal, toItem: containerView, attribute: .trailing, multiplier: 1, constant: 0)
])
}
Hide
private func hide(contentController content : UIViewController)
{
content.willMove(toParentViewController: nil)
content.view.removeFromSuperview()
content.removeFromParentViewController()
}
I have a similar situation where I add a child controller to a visible controller (a popup).
I define the child view controller in interface builder. It's viewDidLoad method just calls setTranslatesAutoresizingMaskIntoConstraints:NO
Then I define this method on the child controller which takes a UIViewController parameter, which is the parent. This method adds itself to the given parent view controller and defines its own constraints:
- (void) addPopupToController:(UIViewController *)parent {
UIView *view = [self view];
[self willMoveToParentViewController:parent];
[parent addChildViewController:self];
[parent.view addSubview:view];
[self didMoveToParentViewController:parent];
NSArray *horizontalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[view]-0-|"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(view)];
[parent.view addConstraints:horizontalConstraints];
NSArray *verticalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[view]-0-|"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(view)];
[parent.view addConstraints:verticalConstraints];
}
then inside the parent UIViewController (the one which is already displayed), when I want to display my child popup view controller it calls:
PopUpNotificationViewController *popup = [[self storyboard] instantiateViewControllerWithIdentifier:@"NotificationPopup"];
[popup addPopupToController:self];
You can define whatever constraints you want on the child controller's view when adding it to the parent controller's view.
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