NSLayoutConstraint programmatically set view frame - ios

I know there is are similar topics, but i cant figure out how to do simple thing, for example, set view frame programmatically with Auto Layout constraints. Its pretty easy to do with Storyboard, but when i try to learn about NSLayourConstraint i realise that i'm not understand topic.
Consider that we have UIView and 3 buttons. First button at top have 3 constraints (leading and trailing, and to top of a view). Other 2 buttons centered horizontally with that button and have equal widths. its pretty easy layout, i upload screenshot:
I have read about visual format language, but what i cant understand is - how to create constraint, for example, that relay to top (or trailing-leading)? Like following:
Task look pretty simple but still, i did not found a way how to do that programmatically with NSLayoutConstraint. Could you please provide a solution? Thanks.

Here's a solution (should go in -viewDidLoad). There are a a couple of things to note:
Firstly, VFL doesn't allow you to create all possible types of constraint. In particular, centering needs to be done with the +constraintWithItem: class method on NSLayoutConstraint.
Secondly, as noted in the comments, you could just use hardcoded left and right pad values in the horizontal VFL string to achieve the centering, but this might cause problems if you need to support different device sizes.
Thirdly, the call to -setTranslatesAutoresizingMaskIntoConstraints: is critical. Programmatic Autolayout will completely fail to work if you forget this. Also you need ensure all views are added to their superviews before setting up constraints, otherwise any constraint string referencing a superview will cause a crash
NSArray *names = #[#"button1",#"button2",#"button3"];
NSMutableDictionary *views = [[NSMutableDictionary alloc]init];
for(NSUInteger i=0;i<3;i++) {
UIButton *b = [[UIButton alloc]init];
NSString *name = names[i];
[b setTitle:name forState:UIControlStateNormal];
views[name] = b;
[b setBackgroundColor:[UIColor redColor]];
[b setTranslatesAutoresizingMaskIntoConstraints:false];
[self.view addSubview:b];
}
//List of values to be used in the constraints
NSDictionary *metrics = #{
#"buttonWidth":#150,
#"bHeight":#50, //button height
#"topPad":#100,
#"vPad":#20 //vertical padding
};
//Horizontal VFL string (repeated for all rows).
for (NSString *buttonName in views.allKeys) {
NSString *horizontalConstraintString = [NSString stringWithFormat:#"|-(>=0)-[%#(buttonWidth)]-(>=0)-|",buttonName];
NSArray *horizontalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:horizontalConstraintString options:0 metrics:metrics views:views];
[self.view addConstraints:horizontalConstraints];
//Can't do centering with VFL - have to use constructor instead. You could also hardcode left and right padding in the VFL string above, but this will make it harder to deal with different screen sizes
NSLayoutConstraint *centerConstraint = [NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:views[buttonName] attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0.0];
[self.view addConstraint:centerConstraint];
}
//Vertical VFL (vertical spacing of all buttons)
NSString *verticalConstraintString = #"V:|-topPad-[button1(bHeight)]-vPad-[button2(bHeight)]-vPad-[button3(bHeight)]-(>=0)-|";
NSArray *verticalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:verticalConstraintString options:0 metrics:metrics views:views];
[self.view addConstraints:verticalConstraints];
[self.view layoutIfNeeded];

Related

Shrink width of UITextField based on growth of another

I am trying to modify the width of a UITextField based on the increasing width of another. Here's an example of my layout:
On the left box (which contains int dialog codes once selected) I want to set this to margin 0 to start with and extend the right UITextField right across. When the left box contains data I want to adjust the right hand text field's border relative to that.
I know how to do this easily in Android but I am not having much luck in Xcode. Can anyone point me in the right direction?
The basic idea is
observe the text changed event
recalculate the width
update the constant property of the width constraint
Here is a simple demo and more edge cases need to be considered.
- (void)viewDidLoad {
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(100, 150, 175, 100)];
container.backgroundColor = [UIColor grayColor];
[self.view addSubview:container];
//initialize text fields
UITextField *leftInput = [[UITextField alloc] initWithFrame:CGRectZero];
leftInput.translatesAutoresizingMaskIntoConstraints = NO;
[leftInput addTarget:self action:#selector(textDidChange:) forControlEvents:UIControlEventEditingChanged];
[container addSubview:leftInput];
UITextField *rightInput = [[UITextField alloc] initWithFrame:CGRectZero];
rightInput.translatesAutoresizingMaskIntoConstraints = NO;
[container addSubview:rightInput];
//setup constraints
NSDictionary *views = NSDictionaryOfVariableBindings(container, leftInput, rightInput);
NSMutableArray *constraints = [NSMutableArray array];
[constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-[leftInput]-[rightInput]-|" options:0 metrics:nil views:views]];
[constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-[leftInput]-|" options:0 metrics:nil views:views]];
[constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-[rightInput]-|" options:0 metrics:nil views:views]];
NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:leftInput attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:0 multiplier:0 constant:minWidth];
[constraints addObject:widthConstraint];
self.widthConstraint = widthConstraint;
[NSLayoutConstraint activateConstraints:constraints];
}
- (void)textDidChange:(UITextField *)textInput {
NSDictionary *attributes = #{NSFontAttributeName: textInput.font};
CGFloat width = [textInput.text sizeWithAttributes:attributes].width;
self.widthConstraint.constant = MAX(minWidth, width);
}
Here is an alternative without using constants. The idea is to set up the autolayout in such a way that it recalculates width of the left text field for you so you simply update the layout when text changes.
First, set hugging priority on left text field to be higher than right text field. Make sure you have these horizontal constraints installed:
Left margin of left text field to container (or other item, simply fix the left margin)
Right margin of left text field should have a fixed horizontal spacing to left margin of right text field (this is the gap between the text fields, standard is 8px but of course use what you want)
Right margin of right text field to the right side of the container or whatever you use to anchor the right side to
This forces the two text fields to occupy some given space between the left and right margins, and autolayout must decide which text field gets priority. By setting hugging priority higher for left text field you state that you prefer the right text field to expand if there is space available, therefore if both fields are empty, the right one will take up the full space. This is why you need to set up greater than or smaller than constraints to limit how small/large your text fields can get.
For now, let's assume we start with both text fields empty. At this point it would be smart to provide a minimum width for the left text field because otherwise it will have a width of 0 and so it won't be possible to enter any text. Minimum size of about 50 should be reasonable to allow for text input, but try and see what works for you.
Remember to capture the text editing changed property on the text field, so assuming you have the text field in a variable named leftTextField, call
[leftTextField addTarget:self action:#selector(leftTextChanged) forControlEvents:UIControlEventEditingChanged];
somewhere in your viewDidLoad or other initialisation method.
Now all that remains is to ask autolayout to recalculate the intrinsic size of the views and update itself. This is done by calling layoutIfNeeded, so your method would look like
- (void)leftTextChanged {
[self.view layoutIfNeeded];
}
Hope this helps.

Why do these Auto Layout constraints for a UIView prevent UIButton subviews from receiving touch events?

I'm using auto layout, programmatically. I've got a simple UIViewController with a few controls, including two UIButtons arranged side-by-side. I often group related controls within a UIView, to act as a container, making the arrangement of groups-of-controls a bit easier to manage. You'll see that below with _iapButtonsView, which holds the two buttons and some spacers.
My question. In the following example, I was caught out by what I thought was a valid change to the constraints, that actually resulted in the UIButtons not receiving touch events.
Code extract - constraints in which the buttons do receive touch events:
- (void)viewDidLoad
{
[super viewDidLoad];
...
_buyButton = [ViewCreationHelper createRoundedBorderButtonBold];
[_buyButton addTarget:self action:#selector(buyTap:) forControlEvents:UIControlEventTouchUpInside];
_restoreButton = [ViewCreationHelper createRoundedBorderButton];
[_restoreButton addTarget:self action:#selector(restorePurchaseTap:) forControlEvents:UIControlEventTouchUpInside];
_iapButtonsView = [UIView new];
_iapButtonsView.translatesAutoresizingMaskIntoConstraints = NO;
[contentView addSubview:_iapButtonsView];
...
[_iapButtonsView addSubview:_buyButton];
[_iapButtonsView addSubview:_restoreButton];
// Constraints
NSDictionary* views = NSDictionaryOfVariableBindings(scrollView, contentView, iapDesciption, _iapButtonsView, _buyButton, _restoreButton, spacer1, spacer2, spacer3);
...
constraints = [NSLayoutConstraint
constraintsWithVisualFormat:#"V:|-25-[iapDesciption]-40-[_iapButtonsView]|"
options:0
metrics:nil
views:views];
[contentView addConstraints:constraints];
constraints = [NSLayoutConstraint constraintsWithVisualFormat:#"H:|-20-[_iapButtonsView]-20-|" options:0 metrics:nil views:views];
[contentView addConstraints:constraints];
constraints = [NSLayoutConstraint constraintsWithVisualFormat:#"H:|[spacer1][_buyButton(==120.0)][spacer2(==spacer1)][_restoreButton(==_buyButton)][spacer3(==spacer1)]|" options:NSLayoutFormatAlignAllCenterY metrics:nil views:views];
[_iapButtonsView addConstraints:constraints];
constraints = [NSLayoutConstraint constraintsWithVisualFormat:#"V:|[_buyButton(==80.0)]|" options:0 metrics:nil views:views];
[_iapButtonsView addConstraints:constraints];
constraints = [NSLayoutConstraint constraintsWithVisualFormat:#"V:|[_restoreButton(==80.0)]|" options:0 metrics:nil views:views];
[_iapButtonsView addConstraints:constraints];
...
}
The constraints in question are the vertical constraints for _iapButtonsView. During development (this is an In-App Purchase screen) I had some debug controls at the bottom, which is why I had the trailing | connecting to the superview's bottom edge, like this:
constraintsWithVisualFormat:#"V:|-25-[iapDesciption]-40-[_iapButtonsView][someSpacer][someControls]|"
When I took those debug controls out, I changed those constraints to be:
constraintsWithVisualFormat:#"V:|-25-[iapDesciption]-40-[_iapButtonsView]"
thinking that was more correct: they're anchored from the top, only, the _iapButtonsView gets its size from its subviews (principally, the two buttons), so I shouldn't connect to the bottom edge of the superview...
With that change, the buttons no longer receive touch events. To experiment, I tried explicitly setting the vertical size of _iapButtonsView, but still not connecting to the bottom edge of the superview, e.g.
constraintsWithVisualFormat:#"V:|-25-[iapDesciption]-40-[_iapButtonsView(==80.0)]"
With those constraints, the buttons still do not receive touch events.
What am I not understanding?
(Edit: I removed the duplicated [contentView addSubview:_iapButtonsView]; in the code, above, per suggestion from daddy warbucks)
One issue, you've called this two times:
[contentView addSubview:_iapButtonsView];
Not sure if this helps, but it could be an issue.
Also, you don't have to use "(==80.0)", just use "(80.0)", or even "(80)" not sure if this helps, but hey, it could, right?

Flexible width constraint

I got stuck with resolving constraints, perhaps someone can help:
Here is the case:
I need myView to have flexible width according to superview width.
If superview has more width than 500 -> myView should have 500.
If superview has less width then 500 -> myView should take all superView width.
[NSLayoutConstraint constraintsWithVisualFormat:#"[myView(==500)]" options:0 metrics:nil views:#{
#"myView" : self.myView,
#"superview" : superview
}];
// If I write myView(<=500), obviously width will be zero.
// I can not add something like this:
// #[tableView(<=superview)]", as width can be less, can be more
So I got stuck here, any thoughts?
Thanks in advance!
Visual Format Language can be kind wonky even by Auto Layout standards, especially when setting priority. The problem is actually conceptual and can be done in IB or with VFL or by the class methods. Anyway, the issue:
When you want some behavior to change in a set way when some condition is met or not met, try switching to priority instead of inequality. In this case, think of the margins: You want to the horizontal margin to be 0 when the total width is under 500, but adding space when more than 500. Constraints you will need:
Required priority 1000: Set myView to less than or equal to 500.
Priority 999: Set myView attached to superview with leading/trailing space=0.
If the space is less than 500, both conditions can be met. If the space is more than 500, than it will start breaking constraints, starting with the lowest priority.
Note that after breaking the margin constraints it won't know where to set the horizontal x placement of myView, so you will need another constraint. Centering in superview will conflict the least, since it can place it horizontally with or without margin constraints broken. There is a way to get it to add space on one side only, but it's a complicated dance-of-the-breaking-constriants leading to messy required programmatic intervention; I think centered-horizontally gets your intended behavior.
You need more than one constraint and the use of priorities. One constraint for myView to equal the superview width as you already have and another for the myView to be NSLessThanOrEqual to 500 as suggested above. Then set the priority of the latter to be greater than the equal width constraint. I think that should be enough for the width. Maybe you'll need a 3rd constraint with lower priority to set the width of myView to 500 if it still shrinks to 0 to avoid ambiguity.
Here's an edit to my answer with some code to illustrate better:
Using visual layout as below allows for the more readable layout (once you're used to the syntax)
NSDictionary *views = #{#"myView" : _myView, #"superView": self.view};
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-100-[myView(40)]" options:0
metrics:nil
views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-(3#999,>=3)-[myView(<=500)]-(3#999,>=3)-|" options:0
metrics:nil
views:views]];
If put a padding of 3 just to illustrate the shrinking to the edges.
If you wanting to center myView in the superview visual layout will be lacking and you'll need to add a long form constraint like this:
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.myView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1 constant:0]];
But all of this could done in Storyboards without any code based on the same logic. If not using Storyboards I try to use the visual layout as much as possible and usually only the long form for centering views or when dynamically laying views where the structure is only known at runtime.
As per your question you need to set constraint to myView. Here's what you need to do:
UIView *myView = [UIView new];
myView.translatesAutoresizingMaskIntoConstraints = NO;
myView.backgroundColor = [UIColor blueColor];
[self.view addSubview:myView];
NSDictionary *viewDictionary = #{#"myView":myView};
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-50-[myView(200)]" options:0 metrics:0 views:viewDictionary]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-10-[myView(<=500)]" options:0 metrics:0 views:viewDictionary]];
NSLayoutConstraint *tailing = [NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:myView attribute:NSLayoutAttributeTrailingMargin multiplier:1 constant:75];
tailing.priority = 999;
[self.view addConstraint:tailing];
Result:
Hope this might help in solving your problem.
You can visit this link for setting auto layout constraints programmatically for advance help.
ref: http://technet.weblineindia.com/mobile/ui-design-of-ios-apps-with-autolayout-using-constraints-programmatically/
ref: https://codehappily.wordpress.com/2013/10/09/ios-how-to-programmatically-add-auto-layout-constraints-for-a-view-that-will-fit-its-superview/

Why is NSLayoutAttributeCenterX centering around 0 instead of container view center?

I am having a problem with NSLayoutAttributeCenterX that i can't figure out.
I created a NIB for a custom view and within this custom view I inserted a UILabel that I want to center in the x axis. And I am then inserting this custom view in my root ViewController's view.
Now, I overrided the "layoutSubviews" method of the custom view to put my constraints there to center the Label within the custom view.
I called the UILable inside this view "appTitle".
Below is the content of the "layoutSubviews" method of my custom view. As you can see there, I used the following constraint method to center the UILabel at the center of the custom view, in the x axis.
NSLayoutConstraint *titleConstraint_H = [NSLayoutConstraint constraintWithItem:self.appTitle attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterX multiplier:1 constant:0];
But, the end result is that the UILabel is centered around x= 0 , instead of x = 160, which is the center of the custom view that contains it. I do not understand why this is happening.
In my simulation I am using an ipHone 5s, in PORTRAIT MODE , and I am setting the width of the custom view to be equal to the width of the phone's frame , which is 320. Thus x = 160 is the x coordinate of the center point.
Below is the code inside the "layoutSubviews"
LLDB output that shows the center of the appTitle label after the constraint has been enacted (po (CGPoint) [self.appTitle center])
LLDB output that shows the center of the custom view that contains the label "appTitle" (po (CGPoint)[self center])
and the final output
I wonder if someone has run into this problem too and has figured it out
- (void)layoutSubviews {
//######### TITLE ####################################
UIFont *font = [UIFont fontWithName:#"Avenir-Black" size:20.0];
UIColor *color = [UIColor blackColor];
NSDictionary *attrsDictionary = [NSDictionary dictionaryWithObjects:#[font,color] forKeys:#[NSFontAttributeName,NSForegroundColorAttributeName]];
NSAttributedString *titleString = [[NSAttributedString alloc] initWithString:#"WHINE-O-METER" attributes: attrsDictionary];
self.appTitle.attributedText = titleString;
// Adjust UILabel frame to size of text
[self.appTitle sizeToFit];
// Center title on horizontal length
NSLayoutConstraint *titleConstraint_H = [NSLayoutConstraint constraintWithItem:self.appTitle attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterX multiplier:1 constant:0];
NSDictionary *viewsDictionary = #{ #"title":self.appTitle};
NSArray *titleConstraint_V = [NSLayoutConstraint constraintsWithVisualFormat:#"V:|-20-[title]-20-|" options:0 metrics:nil views:viewsDictionary];
[self addConstraints:titleConstraint_V];
[self addConstraint:titleConstraint_H];
}
thanks!
That's a lot of code to do something that can be done much more easily in your xib file. My recommendation is to remove all that code and set this up in your xib using auto layout. If you are using auto layout, don't call sizeToFit, just set leading and trailing constraints on the label that contains your text. You should not need to implement layoutSubviews to achieve this.
You should not be adding or modifying constraints in -layoutSubviews. From the docs:
You should override this method only if the autoresizing and constraint-based behaviors of the subviews do not offer the behavior you want.
Rather, you should set up constraints in an override of -updateConstraints. And don't forget to call through to super when you override methods like this. (That may actually contribute to your problem, too. Your override of -layoutSubviews does not call through to super.)

AutoLayout two labels within a TableViewCell?

I'm fairly new to iOS programming and probably don't understand the view hierarchy as well as I should and thus am failing to successfully get two labels within a custom table cell class I have created to autoresize properly. Namely the "translatesAutoresizingMaskIntoConstraints" property has me a little confused.
I am not using storyboards for this part of the code: I have a TableViewController where I create my own tableView in viewDidLoad. In cellForRowAtIndexPath I init my own TableViewCell implementation.
The problem I'm having is that when I set "setTranslatesAutoresizingMaskIntoConstraints" to NO for the table view and the UILabels I create then add my constraints, I get the following error:
"Terminating app due to uncaught exception `'NSInternalInconsistencyException',` reason: 'Auto Layout still required after executing `-layoutSubviews`. UITableView's implementation of `-layoutSubviews` needs to call super.'"
If I comment out the setTranslatesAutoresizingMaskIntoConstraints lines, my app runs however I get the following warning about the constraints:
"Unable to simultaneously satisfy constraints. Probably at least one
of the constraints in the following list is one you don't want. Try
this: (1) look at each constraint and try to figure out which you
don't expect; (2) find the code that added the unwanted constraint or
constraints and fix it. (Note: If you're seeing
NSAutoresizingMaskLayoutConstraints that you don't understand, refer
to the documentation for the UIView property
translatesAutoresizingMaskIntoConstraints)"
Essentially what I want to do is to enter code here have the two labels flush against each other and for them to resize based on orientation/device (I will be setting a background colour on them so want them to look 'continuous')
Can anyone help me out and explain what I am missing? Thanks in advance.
My code for adding the labels is:
self.nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 200.0f, 30.0f)];
self.nameLabel.textColor = [UIColor redColor];
self.nameLabel.font = [UIFont fontWithName:#"Helvetica Neue" size:12.0f];
self.nameLabel.backgroundColor = [UIColor brownColor];
[self.nameLabel setText:#"Test"];
// [self.nameLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.contentView addSubview:self.nameLabel];
...
NSDictionary *viewsDictionary =
NSDictionaryOfVariableBindings(nameLabel, summaryLabel);
NSArray *constraints =
[NSLayoutConstraint constraintsWithVisualFormat:#"|-[nameLabel][summaryLabel]-|"
options:0
metrics:nil
views:viewsDictionary];
I'm fairly new to ios programming and probably don't understand the
view hierarchy as well as I should and thus am failing to successfully
get two labels within a custom table cell class I have created to
autoresize properly. Namely the
"setTranslatesAutoresizingMaskIntoConstraints" property has me a
little confused.
Well, translatesAutoresizingMaskIntoConstraints is a property that is created by Apple to make the transition from Autoresizing (Spring and Struts) to Autolayout easier. Say, you had some AutoresizingMasks for your view and you just switched Autolayout ON without setting any constraints. Then your existing AutoresizingMasks will get converted into constraints which will hold the view in place. So, by default translatesAutoresizingMaskIntoConstraints property is set to be YES. However, when you start adding constraints, in 90% cases they will conflict with the constraints that got created by converting your AutoresizingMasks. So, it is better to turn it off by setting view.translatesAutoresizingMaskIntoConstraints = NO
In your code, the following might have been creating the problems:
The setting of Frame
You should not set frames to objects which you will be adding constraints to. It's a paradigm shift. When you think in Autolayout way, frames are but effects of setting right constraints who combinedly determine the frame of the view in question.
So, please remove the frame setting.
self.nameLabel = [[UILabel alloc] init]; will suffice.
Setting proper constraints
Your Code:
NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(nameLabel, summaryLabel);
NSArray *constraints =
[NSLayoutConstraint constraintsWithVisualFormat:#"|-[nameLabel][summaryLabel]-|"
options:0
metrics:nil
views:viewsDictionary];
NameLabel
Now, the above constraints tells us the nameLabel should be horizontally (as you have not mentioned H: or V:) spaced "standard" distance (20px) from container, adjacent to the summaryLabel.
But what about its Y position and Width and Height?
So we need more constraints.
summaryLabel
Same is applicable for summaryLabel.
So, lets define them properly:
NSDictionary *viewsDictionary =
NSDictionaryOfVariableBindings(nameLabel, summaryLabel);
NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:#"H:|-[nameLabel(100)][summaryLabel]-|" options:0 metrics:nil views:viewsDictionary];
NSArray *constraints1 = [NSLayoutConstraint constraintsWithVisualFormat:#"V:|-[nameLabel(30)]" options:0 metrics:nil views:viewsDictionary];
NSArray *constraints2 = [NSLayoutConstraint constraintsWithVisualFormat:#"V:|-[summaryLabel]" options:0 metrics:nil views:viewsDictionary];
NSArray *constraints3 = [NSLayoutConstraint constraintsWithVisualFormat:#"V:[nameLabel(==summaryLabel)]" options:0 metrics:nil views:viewsDictionary];
[self.view addConstraints:constraints];
[self.view addConstraints:constraints1];
[self.view addConstraints:constraints2];
[self.view addConstraints:constraints3];
Now your views will look fine.
At any point of time, to check if your views are missing any constraints, pause the debugger and type the following in the console
po [[UIWindow keyWindow] _autolayoutTrace]
it will show which of your views are having AMBIGUOUS LAYOUT
Also, remember in Storyboard/IB if the constraints are showing as "orange" colour, you need more constraints to define the objects position. Once you have added all necessary constraints, the constraints colours turn to "blue"
First, are you adding constraints to self.contentView after creation?
Second, maybe your constraint set is insufficient for autolayout and it creates own constraints based on autoresizing mask. Try to add vertical constraints and width constraints for labels.

Resources