AutoLayout Limitations for an Auto Resistant View Created in ViewController 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 would like to switch to AutoLayout and therefore add

 view.translatesAutoresizingMaskIntoConstraints = NO; 

to the loadView method. Now I have to specify the same restrictions that were previously auto-generated. 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 such restrictions should come with a 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 illegal. 

So what should the correct Contraints look like?

+6
source share
4 answers

You need to set restrictions on the supervisor. The exception is thrown by reference to the supervisor by passing "|" in visual format. If you update your code as follows, 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 probably want to check something other than 0 supervisor restrictions, but that should help.

+8
source

You don’t need to set limits on the root view, as Matt Neuburg explains chapter 19 of his iOS 6 programming book in the Manual Layout section :

We did not bother to give our view (self.view) reasonable frame. This is due to the fact that we rely on someone else to form our perceptions accordingly. In this case, “someone else” is a window that responds to the fact that its rootViewController property rootViewController set to the view controller, creating the view controller view appropriately as the root view before placing it in the window as a subview.

+5
source

The problem with CEarwood's approach is that it is a ViewController, and its view is not subtype of any other view, so calling self.view.subview just makes it null. Remember that Apple documentation and recommendations strongly indicate that the UIViewController occupies more or less the entire screen (in addition to the navigation bar or tab bar, etc.).

Palimondo's answer is basically correct: your UIViewController needs to run its view in loadView, but it does not need to specify its frame or restrictions, as they are automatically set to the window frame and restrictions. This is exactly what the default is done if you do not implement loadView yourself.

+5
source

I'm not sure if you need to set limits for the root view of the window.

However, your limitations look right, I think you get the exception because it is:

  [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[view]|" options:0 metrics:0 views:views]]; 

uses | to represent the view view. As a root level, it does not have a supervisor. Something like this might work better:

 - (void)loadView { UIView *customView = [[UIView alloc] init]; [self.view addSubview:customView]; NSDictionary* views = @{@"customView" : customView}; [customView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[customView]|" options:0 metrics:0 views:views]]; [customView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[customView]|" options:0 metrics:0 views:views]]; } 
+1
source

Source: https://habr.com/ru/post/943809/


All Articles