user1459524
user1459524

Reputation: 3603

Setting Constraints programmatically different from setting them in IB?

I am new to Auto Layout in iOS. I really like the concept in principle, but it's driving me nuts trying to get the simplest things done. I suspect I'm still missing some simple underlying principle. I am trying to learn by doing and get the basics right before actually working with it in an app, so I'm creating very simple test projects. Here's one as simple as it gets that doesn't work as expected. First the part that works. In IB, I add a View to fill the entire viewcontroller, and XCode automatically sets the constraints to Top/Bottom/Leading/Trailing and the Space to 0. When done with IB, it works as expected:

enter image description here

rotates to

enter image description here

Great!

Now I am trying to do the same thing in code:

- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UIView *redView = [[UIView alloc] initWithFrame:self.view.bounds];
redView.backgroundColor = [UIColor redColor];
[self.view addSubview:redView];

redView.translatesAutoresizingMaskIntoConstraints = NO;

[self.view addConstraint:[NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1.0f constant:0.0f]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeading multiplier:1.0f constant:0.0f]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1.0f constant:0.0f]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeading multiplier:1.0f constant:0.0f]];
}

That's all the code there is other than the default code for a Single-view application.

When I run the above code, trying to mirror the same thing as I get with IB programmatically, I get this after rotation:

enter image description here

How come that the same constraints lead to different results? It's probably something really simple and embarrassingly stupid that I am missing. Help!!!

Upvotes: 9

Views: 20973

Answers (3)

TommyBs
TommyBs

Reputation: 9646

I know this is old, but I think the issue with your constraints was that you were confusing what trailing etc. represent. I've amended your code to the following and it now fills the screen as expected:

       UIView *redView = [[UIView alloc] initWithFrame:self.view.bounds];
redView.backgroundColor = [UIColor redColor];
[self.view addSubview:redView];

redView.translatesAutoresizingMaskIntoConstraints = NO;

[self.view addConstraint:[NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1.0f constant:0.0f]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeading multiplier:1.0f constant:0.0f]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTrailing multiplier:1.0f constant:0.0f]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0f constant:0.0f]];

You were setting the trailing constraint equal to the bottom (trailing is actually the right hand side not the bottom and you were relating the top constraint to the left hand side (leading)

Upvotes: 7

Ben Wheeler
Ben Wheeler

Reputation: 7364

Instead of Leading and Trailing, use Top and Bottom. Note that you are mixing these up in original post. Leading and Trailing seem to confuse people!

Upvotes: 1

user1078170
user1078170

Reputation:

Here's how I would do this:

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[redView]|"
                                                                  options:0
                                                                  metrics:nil
                                                                    views:NSDictionaryOfVariableBindings(redView)]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[redView]|"
                                                                  options:0
                                                                  metrics:nil
                                                                    views:NSDictionaryOfVariableBindings(redView)]];

AutoLayout in IB can be a pain and I found that familiarizing myself with the Visual Format Language was less work than constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant:

Upvotes: 6

Related Questions