Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AutoLayout constraints for a autoresizing view created in ViewController's loadView

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?

like image 692
Tobias Müller Avatar asked Apr 28 '13 09:04

Tobias Müller


2 Answers

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.

like image 196
CEarwood Avatar answered Nov 06 '22 02:11

CEarwood


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 its rootViewController 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.

like image 5
Palimondo Avatar answered Nov 06 '22 02:11

Palimondo