My UIViewController
creates its view by overwriting the loadView method:
- (void)loadView {
UIView *view = [[UIView alloc] init];
view.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
self.view = view;
}
Now I'd like to switch to AutoLayout and therefore add an
view.translatesAutoresizingMaskIntoConstraints = NO;
to the loadView method. Now I have to specify the same constraints which were autogenerated before. My approach was to overwrite updateViewConstraints with
- (void)updateViewConstraints {
if (0 == [[self.view constraints] count]) {
NSDictionary* views = @{@"view" : self.view};
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[view]|" options:0 metrics:0 views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[view]|" options:0 metrics:0 views:views]];
}
[super updateViewConstraints];
}
But I get an exception because I think this kind of constraints should go with the super view:
*** Terminating app due to uncaught exception 'NSGenericException', reason: 'Unable to install constraint on view. Does the constraint reference something from outside the subtree of the view? That's illegal.
So, how do the correct Contraints have to look like?
You need to set the constraints on the superview. The exception is caused by referencing the superview by passing "|" in the visual format. If you update your code like the following it will work:
- (void)updateViewConstraints {
if (self.view.superview != nil && [[self.view.superview constraints] count] == 0) {
NSDictionary* views = @{@"view" : self.view};
[self.view.superview addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[view]|" options:0 metrics:0 views:views]];
[self.view.superview addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[view]|" options:0 metrics:0 views:views]];
}
[super updateViewConstraints];
}
In practice you'll probably want to check for something other than 0 constraints on the superview but this should help.
You don't have to set the constraints on your root view as Matt Neuburg explains the Chapter 19 of his Programming iOS 6 book, in section Manual Layout:
We have not bothered to give our view
(self.view)
a reasonable frame. This is because we are relying on someone else to frame the view appropriately. In this case, the “someone else” is the window, which responds to having itsrootViewController
property set to a view controller by framing the view controller’s view appropriately as the root view before putting it into the window as a subview.
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