Rich's Mad Rants
Powered by Squarespace

Entries in Auto Layout (2)


Mastering Auto-Layout Workshop

I have some good news, and I have some bad news. The bad news is, we had to cancel the iCloud MacTech workshop. I think people have either just given up on iCloud, or (hopefully) the new API is working so well that they don't need any help.

The good news is, I will now be talking about one of my other favorite (and possibly equally controversial) topics, Auto Layout.

Here are the details:

When an Apple developer is deals with a view’s size changes, they need to adjust the layout of its content to fit within its new bounds. Traditionally, we did this using autoresizing masks. These have the advantage of being easy to understand. Unfortunately, they are also limited. In all but the most basic views, we would need to supplement our autoresizing masks with custom code to programmatically layout some or all of our subviews.

Starting with OS X 10.7 Lion and iOS 6, Apple introduced Auto Layout to help us better manage changes in our user interfaces. Auto Layout promises to fill the gaps left by autoresizing masks. In theory, it should completely eliminate the need to programmatically layout our view hierarchies. Furthermore, Auto Layout lets our views adapt to internal changes -- this means our views can automtaically adjust their size in response to changes in their content.

This is especially important with the introduction of iOS 7 and likely Mavericks. Dynamic Type allows users to change the size of the fonts in all supporting applications. If we want to support Dynamic Type, we must re-layout our user interface whenever the font size changes. In addition, many user interface elements have changed size between iOS 6 and iOS 7. If we want to support both operating systems, we need to adjust our user interface appropriately. Auto Layout helps solve both of these problems.

Auto Layout is declarative, constraints-based layout engine. Instead of specifying a view’s size or location, Auto Layout lets us define complex relationships between views, giving us an incredible amount of power--but this power comes at a cost. Auto layout has a steeper learning curve than Autoresizing.

This workshop will help you get over the steepest part of that curve. Specifically, Mastering Auto Layout will cover:

  • The theory behind Auto Layout.
  • Programmatically setting Auto Layout constraints using NSLayoutConstraint.
  • Setting and modifying Auto Layout constraints in Interface Builder.
  • Debugging Auto Layout issues.
  • Best practices for using Auto Layout with iOS 7.
  • Using Auto Layout to support Dynamic Type.
  • Using Auto Layout to support both iOS 6 and iOS 7.

This is a hands-on workshop. Students will get experience adding, modifying and debugging Auto Layout constraints through a series of lab exercises. The class will be taught using iOS 7; however, most of the material will apply to OS X development as well.

You can get more information at the MacTech Conference site. If you're interested in signing up, you can also use my speakers link to get a discount.

I hope to see you there!


Understanding Auto Layout

The user interface is the main, driving feature of most iOS applications. It is our primary means of communicating with our users, and in many cases, their opinion of our apps is heavily influenced by their experience with our UI. Therefore, it’s worth taking the time and effort to ensure our interfaces are attractive, responsive and (above all else) highly useable.

Part of building a high-quality user interface includes controlling how they respond to changes in our view’s size. These changes may occur for a number of reasons--most obviously, when the user rotates the device. If the interface supports auto-rotation (and all applications should. Few things frustrate me more than an application that refuses to let me choose how I hold my device--Yes, I’m looking at you, Flipboard for iPhone) then we must adjust our layout as the view stretches from portrait to landscape mode and back.

Somewhat surprisingly, other things can also cause variations in view size. In some cases, it may be device driven. For example, opening an app on the iPhone 5 requires an additional 88 points of height (or 176 actual pixels). System events can also drive changes. For example, if you have an active phone call in the background, the system will display a green bar across the top of the screen. This shortens our display by another 20 points. The system similarly displays a red bar when recording audio.

Bottom line, we need to make sure our user interface adapts to any possible size or orientation. There are 3 basic approaches. We can hard code the position and size of our subviews--programmatically adjusting them whenever our root view’s size changes. Alternatively, we can use the view's Autoresizing mask to define how our user elements will resize and reposition themselves in response to these changes. Finally, we can define our view’s layout using Auto Layout constraints.

Programmatically Laying Out Views

By default, all views have a fixed height and width. Their location is also defined as a fixed distance from the top and a fixed distance from the left edge of their superview. We can see this in the view's frame property. It has an origin (x and y coordinates for its upper left corner) and a size (width and height). While this lets us specify an unambiguous layout for our controls--it doesn’t give us any flexibility. If the view’s size changes, we must re-layout all our interface elements, cycling through all our interface elements and repositioning and resizing each one.

Fortunately, this is fairly easy. We can reposition a view by modifying either it’s center or frame property. We can also resize it by modifying either the frame or bounds properties. Of course, the calculations required to determine the new size and position are often somewhat complex.

If we want to respond to changes in our superview’s size, we will typically modify these properties in our view controller’s viewWillLayoutSubview or viewDidLayoutSubview method. We can also implement a custom view’s layoutSubviews method to fine tune the layout of any of its subviews.


While programmatically repositioning one or two subviews isn’t too hard, this quickly becomes unwieldy for complex user interfaces. Ideally, we would like to automate some, if not all, of this work. In many cases, we can do this by simply setting each view's Autoresizing mask.

Autoresizing lets us define 6 parameters that describe how a view will respond to changes in its superview size. These are the left margin, right margin, top margin, bottom margin, height and width. Each of these can be set to be either fixed or flexible.

Here are the rules: Fixed parameters have a set size. They will not change as the superview shrinks and grows. Flexible parameters, on the other hand, can shrink and grow. Left margin + width + right margin will always equal the superview’s width. Similarly top margin + height + bottom margin will equal the superview’s height.

If you have more than one flexible parameter for a given dimension, the changes in that dimension will be split between them. On the other hand, the margins have a higher priority than the height and width--so if you set all three to fixed, the size parameter will be ignored, and the height (or width) will change with the superview.

This system has several advantages. It is relatively simple. Use it once or twice and you understand how it handles most layout situations. Its biggest problem, however, comes from this simplicity. It can only handle a few, simple layouts. Specifically, it works best when only one element in a row (or column) is flexible. Trying to manage multiple flexible elements tends to produce an interface that feels somewhat sloppy, as the space between elements grows and shrinks with the view’s size.

If we want more precise complex changes, we either need to manage the layout programmatically or switch to Auto Layout.

Auto Layout

Apple created Auto Layout to fill in the gaps left by Autoresizing. In theory, it should eliminate the need to programmatically lay out our view hierarchies. Auto Layout lets us define complex relationships between views, giving us a lot more power--but this power comes at a cost. Auto Layout is much harder to understand and setup than Autoresizing.

Instead of specifying a view’s position or size, we specify a number of constraints. These are represented as linear equations, as shown below:

Attribute_1 = Multiplier * Attribute_2 + Constant

The attributes can be any of the following:

Left Edge
Right Edge
Top Edge
Bottom Edge
Leading Edge
Trailing Edge
Not An Attribute

Of these, three merit special mention. Leading edge is the first edge you run across based on the current local’s reading direction. For left-to-right languages like English, this would be the left edge. Trailing edge is the opposite; the right edge for English. By using the Leading Edge and Trailing Edge (instead of Left Edge and Right Edge), our UI elements will automatically reorder themselves when we switch from a left-to-right language to a right-to-left language.

Not An Attribute indicates that the attribute (and multiplier) will not be used in this calculation. We can use this to define constant constraints.

Here are some examples in pseudo-code:

// Example 1: Setting a constant height
View’s Height = 0.0 * Not An Attribute + 40.0;

// Example 2: Setting a fixed distance between two buttons.
Button_2’s Leading Edge = 1.0 * Button_1’s Trailing Edge + 8.0;

// Example 3: Make two buttons have the same width
Button_2’s Width = 1.0 * Button_1’s Width + 0.0;

// Example 4: Centering a view in its superview
View’s CenterX = 1.0 * Superview’s CenterX + 0.0;
View’s CenterY = 1.0 * Superview’s CenterY + 0.0;

// Example 5: Giving a view a constant aspect ratio
View’s Height = 2.0 * View’s Width + 0.0;

To use Auto Layout, we define a set of rules, and the system tries to fulfill them. Unfortunately, like most rules-based systems, each individual constraint may seem simple enough--but as they are combined, they may create unintended consequences. As the number of constraints grow, it gets harder and harder to accurately guess what the system will do at runtime.

Sufficient, Non-Ambiguous Layouts

To generate predictable results, we must declare constraints that are both sufficient and non-ambiguous. Typically this means we need at least four constraints per subview. One to define its Height, one to define its Width, one to define its x-coordinate and one to define its y-coordinate. Of course, there are many ways to skin this cat, but as long as we declare two of the possible attributes for each dimension, we should be fine. For example, to specify a view’s Y axis, we could specify the Top and Bottom, Top and Height, Bottom and Height, Center Y and Height or Baseline and Height. Other combinations are possible (Top and Center Y, for example), but these will be somewhat rare.

We also need to avoid assigning too many constraints--creating conflicts that cannot be simultaneously satisfied. For example, I cannot define a view’s Top, Height and Bottom. One of these will need to change as the superview’s height changes.

So far his seems fairly straightforward. Just create two and only two x-dimension constraints and two and only two y-dimension constraints for each subview in your view hierarchy. You should be good to go.

Of course, nothing about Auto Layout will ever be that straightforward. The problem is, I lied.

Actually constraints don’t have to be linear equations. They can also be inequalities. For example, we could define a minimum width for a view as shown below:

View’s Width >= 0.0 * Not An Attribute + 20.0;

Note: when you use inequalities, you will need more than four constraints to specify an unambiguous layout. To make matters worse, each constraint also has a priority. Priorities range from 1 to 1,000. If it’s set to 1000, the constraint is required. Anything less and the constraint is optional. The system will try to satisfy all the optional constraints in order from highest priority to lowest.

Finally, some controls have a natural size. Rounded rectangle buttons, for example, are typically 44 points tall and wide enough to hold their title text. Text fields, on the other hand, are 30 points tall, but don’t have a preferred width. We say that these views have an intrinsic size--and this generates a whole new set of constraints for us.

Intrinsic Sizes

We can set the intrinsic size of a UIView subclass by overriding its intrinsicContentSize method. This method should return a CGSize. This could be a fixed size, or a size calculated from the view’s contents. If the view does not have an intrinsic size for a given dimension, it should set that dimension’s value to UIViewNoIntrinsicMetric (-1.0). By default, UIView returns {UIViewNoIntrinsicMetric , UIViewNoIntrinsicMetric}.

If we need to recalculate the intrinsic size (for example, after changing the view’s content), we should call invalidateIntrinsicContentSize. The system will then use the new intrinsic size on the next layout pass.

Auto Layout creates four constraints based on a view’s intrinsic size; two pairs of inequalities per axis. The compression resistance maintains the view’s minimum height and width, while the content hugging defines its maximum. The linear equations are shown below.

// Compression Resistance
View’s Height >= 0.0 * Not An Attribute + View’s Intrinsic Height;
View’s Width >= 0.0 * Not An Attribute + View’s Intrinsic Width;

// Content Hugging
View’s Height <= 0.0 * Not An Attribute + View’s Intrinsic Height;
View’s Width <= 0.0 * Not An Attribute + View’s Intrinsic Width;

By default, the content hugging priority is set to 250, and the compression resistance priority is set to 750. We can modify the priorities for these constraints by calling setContentCompressionResistancePriority:forAxis: and setContentHuggingPriority:forAxis:.

This gives us considerable flexibility when it comes to our views. For a button, we might set both the compression resistance and the content hugging to a priority of 1,000. This would force the button to a fixed size. A text field, on the other hand, might have its content hugging priority for the X axis set to NSLayoutPriorityDefaultLow, all others set to 1,000. This would give it a fixed height and a minimum width, but would allow it to grow to fill the available space.

Specifying Constraints

There are four ways to set up a view’s constraints. We can simply use the default constraints. We can programmatically define each constraint. We can programmatically set multiple constraints using the Visual Format language. Finally, we can let Interface Builder manage the constraints for us.

I’ll talk about constraints and Interface Builder in a bit. For now, let’s look at doing it in code.

Default Constraints

Whenever we add a view to the view hierarchy, the system automatically generates a set of constraints to match the view’s Autoresizing mask. By default, all views have an Autoresizing mask with a fixed left margin, fixed top margin, fixed height and fixed width.

Sometimes these default constraints can prove useful. In many cases, it might be easier to define the Autoresizing mask, and use the auto-generated constraints, rather than creating your constraints by hand. Additionally, the default constraints let us continue to resize and move a view by modifying its frame, bounds and center properties. This can be particularly helpful when animating views (see Constraints and Core Animation for more information).

However, we will often want to use our own constraints--and that means disabling the default constraints. To disable these, simply call setTranslatesAutoresizingMaskIntoConstraints: and pass NO.

Note: Default constraints are automatically disabled for any views added using Interface Builder.

Constraint API

We can programmatically create our own constraint using NSLayoutConstraint’s constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant: method. This is a direct translation of the linear equation shown earlier.

The first two arguments define the view and the attribute that we are constraining. The attribute must be of type NSLayoutAttribute. NSLayoutAttribute is defined below:

enum {
NSLayoutAttributeLeft = 1,

NSLayoutAttributeNotAnAttribute = 0
typedef NSInteger NSLayoutAttribute;

Next we pass an NSLayoutRelation to define the equation's type. NSLayoutRelation is defined below:

enum {
NSLayoutRelationLessThanOrEqual = -1,
NSLayoutRelationEqual = 0,
NSLayoutRelationGreaterThanOrEqual = 1,
typedef NSInteger NSLayoutRelation;

The next two arguments define the view and the attribute for the right side of the equation. Again, the attribute must be an NSLayoutAttribute. These are followed by the multiplier and the constant (both CGFloats).

So, the following call:

NSLayoutConstraint *constraint =
[NSLayoutConstraint constraintWithItem:view1 
        attribute:attribute1 relatedBy:relationship 
       attribute:attribute2 multiplier:mx constant:c];

Defines the following linear equation:

view1.attribute1 view2.attribute2 * mx + c;

Once we have the constraint, we still need to add it to the system. Constraints should be added to the closest ancestor of both views in the constraint. By ancestor, I mean either the view itself, it’s superview, it’s superview’s superview, or any other superview moving up the view hierarchy.

For example, if I was creating a constraint between a view and it’s superview, I would add the constraint to the superview. If I was adding a constraint between two sibling buttons, I would add the constraint to their shared superview.

We add constraints by calling UIView’s addConstraint: method and passing our constraint.

The following code unambiguously defines a set of constraints for a button and a text view. In a left-to-right language (like English) the button should be a constant distance from the superview’s upper left corner. It also has a fixed width. The text field should be a fixed distance from the button’s right edge. It is also vertically centered on the button. Finally, the right edge of the text field should be a fixed distance from the superview’s right edge. Therefore, as our superview resizes, the text field’s width will grow and shrink to appropriately fill the space.

    // Setup Button’s Constraints
    NSLayoutConstraint *buttonX =
     attribute:NSLayoutAttributeLeft multiplier:1.0
    [view addConstraint:buttonX];

    NSLayoutConstraint *buttonY =
    [view addConstraint:buttonY];

    // Setup Button’s Intrinsic Size Priorities

    // Setup Textfield Constraints.
    NSLayoutConstraint *textX =
    [view addConstraint:textX];

    NSLayoutConstraint *textY =
    [view addConstraint:textY];
    NSLayoutConstraint *textWidth =
     attribute: NSLayoutAttributeTrailing
     attribute: NSLayoutAttributeTrailing
    [view addConstraint:textWidth];

In many ways, these are the easiest constraints to understand. However, as you can see, they require a lot of typing. Fortunately, the Visual Formatting language greatly reduces this--but it can also obscures some of the details, making it somewhat harder to understand, at least until you wrap your head around it.

Visual Formatting Syntax

Hands up if you ever spent an afternoon “drawing” ASCII art. This feature is for you.

NSLayoutConstraint supports a visual formatting syntax for constraints. This allows us to “draw” our constraints using an ASCII-art like syntax. The full details can be found at Cocoa Auto Layout Guide > Visual Format Language, but I’ll go through the basics here.

We start by creating an NSString that defines a group of constraints. These strings will use the symbols shown below:

Symbol Meaning
| The edge of the containing superview.

Specifies a view in our UI. Optional arguments can be used to declare the view’s width and the width’s priority.

The width and priority values can be literal numbers or constants. The width value can also be an inequality.

You can also set a view’s width equal to another view. Simply use the other view’s view string for the width.

Finally, we can create complex arguments by providing multiple width@priority pairs separated by commas.


These represent the space between views. If no width is specified, the system will use standard spacing.

The width and priority can be a literal number or constant.

The width value can also be an inequality. And we can create complex arguments by providing multiple width@priority pairs separated by commas.


Used to refer to a view in the views dictionary.


Used to refer to constant values in the metrics dictionary. These can be used for width and priority values.


Used to specify the relationship when setting inequalities. By default, relationships are assumed to be equal (==).


Vertical layout. All descriptions that refer to width refer to height instead.

Note: Do not use any spaces in your visual format string.

Here are a few examples:

Sets the standard spacing between the superview’s leading edge and view1’s leading edge.

Sets the standard spacing between the leading edge of view2 and the trailing edge of view1.

Aligns the leading edge of view2 to the trailing edge of view1. There will be no space between the views.

Set’s the standard vertical spacing between the superview’s top and view1’s top.

Sets view’s width to 200 points.

Sets view’s width to 200 points or less.

[view(>= 50,<=200)]
Sets view’s width to greater than 50, but less than 200 points.

Sets view1’s width equal to view2's width. Note that the equal relationship is optional, however it can make the formatting string easier to read.

Sets view’s width to 200 points, and its priority to 500.

Sets view’s width to the standard constant. Also sets its priority to the high constant.

We can also combine these strings into complex statements. The example below lays out three equal-sized buttons using standard system spacing between all the elements.


We create these constraints using NSLayoutConstraint’s constraintsWithVisualFormat:options:metrics:views: method. The first argument is our visual formatting string. The second argument specifies how the elements should be aligned, and whether we should use LTR, RTL or Leading-To-Trailing relationships. Finally we pass in two dictionaries. The first defines our constants, the second our list of views.

The keys in these dictionaries must match the metric_strings and view_strings used in our visual formatting. The values must be an NSNumber (for metrics) or UIView (for views).

While we can create the view dictionary by hand, we can also use the NSDictionaryOfVariableBindings() function to automatically build one for us. To call this method, pass in our views as arguments. It returns a dictionary that uses our view’s name as the key.

This means, the following two lines of code are equivalent:

NSDictionary *views = NSDictionaryOfVariableBindings(view1, view2, view3, view4);
NSDictionary *views = @{@”view1”:view1, @”view2”:view2, @”view3”:view3, @”view4”:view4};

Note that constraintsWithVisualFormat:options:metrics:views: returns an array of constraints. We can add these constraints to a view by calling addConstraints:.

So, we can redefine our button and text field’s constraints using visual formatting, as shown below:

    NSDictionary *views =
    NSDictionaryOfVariableBindings(myTextField, myButton);
    // Defines both the horizontal constraints and the vertical alignment
    NSArray *constraints =
     options:NSLayoutFormatAlignAllCenterY | NSLayoutFormatDirectionLeadingToTrailing
    // Define’s the button’s vertical position
    NSArray *verticalConstraints =
    [view addConstraints:constraints];
    [view addConstraints:verticalConstraints];

    // Still need to set the button intrinsic size priorities

It’s still a large chunk of code, but we’ve managed to compress five separate constraints into two visual syntax calls. Obviously, the more UI elements you have in each row or column, the greater the savings.

However, there are some limitations. For example, we cannot set a view’s width relative to its height. If we want that sort of relationship, we will need to explicitly define the constraint in code.

Interface Builder and Constraints

So far, so good. However, the real problems start cropping up when we start mixing Auto Layout and Interface Builder.

Note: we can enable Auto Layout on a storyboard-by-storyboard (or nib-by-nib) basis. Open the storyboard, and switch to the File Inspector. In the Interface Builder Document section, look for the Use Autolayout checkbox. If this is checked, the system will create Auto Layout constraints for you. Otherwise, it will layout the interface using Autoresizing masks.

Enabling Auto Layout

If any view in our view hierarchy uses Auto Layout, then the entire hierarchy will use Auto Layout. However, since the system will auto generate constraints based on our Autoresizing settings, we (hopefully) won’t notice the difference when mixing Auto Layout and Autoresizing. Also, Auto Layout is enabled by default for any new nibs or storyboards created using Xcode 4.5 or later.

When Auto Layout is enabled, Interface Builder automatically generates constraints as we drag, drop, resize and move elements in our user interface. It tries to guarantee that we have a set of constraints that unambiguously define the layout without creating any conflicts.

As you drag elements, the familiar blue guidelines now have a new meaning. With Autoresizing, they just represent the recommended spacing as defined in Apple’s HIG. With Auto Layout, they indicate the constraints that Interface Builder will create. Once you drop the interface element, these will turn into blue I-bars, visually displaying the constraints. For example, in the image below, Interface Builder generates three constraints for our button: left margin, top margin and width.

Constraints appear as blue I-bars

If you select a UI element, then hold down option and move the mouse over other views. Interface Builder will show you the size of the constraints between the selected view and the view you are hovering over in red.

Constraint values appear in red.

We can examine these constraints in both the Document Outline and the Size Inspector. We can also select a constraint and edit it’s properties in the Attribute Inspector. This allows us to change the relationship, priority, even the size. We can even create outlets for our constraints--letting us modify them or (in extreme cases) delete them programatically.

Editing a Constraints Attributes

Finally, we can add additional constraints by clicking on the Pin control.

Pin Control

This gives us a number of options. For example, we can pin our trailing edge to the superview’s right side.


As you can see, this creates an additional constraint. Since the button’s width has a lower priority than the trailing edge space, the button’s size will change as the device is rotated.


Let’s take a closer look at the Widths and Heights Equally pins. These let us create a number of views that have the same size. For example, to create a number of buttons with the same width, simply lay them out so they have the proper spacing constraints (I-bars between each of the buttons, and between the end buttons and the superview). These constraints are important. The system won’t enable Widths Equally unless they are set. Once everything’s ready, select all the buttons and pin Widths Equally. Interface Builder handles the rest.

For simple layouts, Interface Builder sets up the constraints as we expect, and everything just works. In these cases, it can be a lot easier than using Autoresizing. We don’t need to remember to go into the Size inspector to set up our Autoresizing mask. However, as the UI becomes more complex, Interface Builder may begin making incorrect or odd-seeming choices.

My biggest complaint with Interface Builder is that it often adds constraints that I don’t want--and getting rid of those constraints can be both difficult and frustrating. You’ll have to spend some time playing around with it before you reach your own level of comfort, but here are a few suggestions to help keep you sane.

Pay careful attention to the guidelines as you add, move or resize UI elements. If you want a constraint defining the space between a button and a text field, make sure you see the little blue guide line as you bring them close together. No guideline, no constraint.

Also, be aware that Interface Builder may recreate any or all its constraints whenever you make a change. This is particularly important when add your own constraints or modify the attributes of existing constraints. If you drag a new item onto the scene, Interface Builder may delete some or all of your custom constraints.

So, I recommend trying to place all your interface elements in the scene first. Then check and see how the view behaves as you rotate it. You can then start placing custom constraints or modifying the priority of constraints to fine tune the scene's behavior.

If things get too confusing, try turning Auto Layout off, then turning it back on. This usually clears all the custom constraints, and forces Interface Builder to recreate a standard set of constraints. You can then try modifying it again.

As a last resort, you can create outlets to troublesome constraints and programmatically delete them (you can also programmatically search through a view’s constraints, looking for ones to delete--but I’ll leave that as an exercise for the insane). Most of the time, this shouldn’t be necessary. Simply giving the offending constraint a very low priority should solve the problem. However, if you plan to programmatically add custom constraints (e.g. constraints that Interface Builder cannot setup for you), you may need to clean up the existing constraints to avoid conflicts.

Constraint Timing

Constraints are processed in three phases: Update Constraint, Layout and Display. The Layout and Display phases should be familiar to experienced iOS developers. Auto Layout just adds the Update Constraint phase and made some modifications to the Layout phase.

Update Constraints Phase

First, the constraints are updated. This starts with the leaf views and works up the view hierarchy towards the application’s window. If a view’s constraints need to be updated, the system will call the view’s updateConstraints method. We can override this method in our view subclasses to dynamically provide constraints at runtime.

We should never call updateConstraints directly. Instead, call setNeedsUpdateConstraints. This will mark the view for updating, and the system will call updateConstraints for us on the next pass through the Update Constraints phase.

Note: updateConstraints may not be called when a view is added to the view hierarchy. If you’re programmatically providing constraints in updateConstraints, and they don’t appear to be used, you may need to call setNeedsUpdateConstraints immediately after adding your custom view.

UIViewController has a similar method named updateViewConstraints. This method is called after its view’s updateConstraints method. We can alternatively override updateViewConstraints to programmatically provide constraints at the controller layer. updateViewConstraints is also triggered by setNeedsUpdateConstraints.

If we want to invalidate a view’s constraints, we should remove the old constraints, then call setNeedsUpdateConstraints. Our custom updateConstraints or updateViewConstraints methods can then provide the new constraints.

Layout Phase

The Layout phase proceeds in a similar manner, however it starts with the window and works down towards the leaf views. Again, if a view’s layout needs to be updated, the system will call the view’s layoutSubviews method. We indicate that a view's layout needs to be updated by calling the setNeedsLayout method.

Before Auto Layout, the default implementation of layoutSubviews did not do anything. However, we could override this method to provide our own custom layouts. Now, with Auto Layout enabled, the view will take its list of constraints and calculate the proper bound, center and frame properties for its contained views.

Note: layoutSubview’s documentation still says that the default implementation does nothing. However, the above description was implied in the WWDC 2012 presentations, and I have confirmed the timing through experimentation.

While I do not recommend mixing code that directly modifies the bounds, center and frame with Auto Layout, if you need to do this, be sure to set your custom values after the call to [super layoutSubviews]. Otherwise the system will clobber your values whenever it derives new values from the constraints (also see Constraints and Core Animation).

Display Phase

Finally, we have the Display phase. This works exactly as it did before Auto Layout. The system will call drawRect: as necessary for our views. We can trigger drawing by calling setNeedsDisplay or setNeedsDisplayInRect:.

Other Constraint Methods

There are a few other methods we can override to help control Auto Layout. These may not be as useful in our day-to-day coding, but it’s nice to know that they are there.

The first is requiresConstraintBasedLayout. This UIView class method returns NO by default. Our custom view subclasses should override this to return YES if they require Auto Layout.

Note: In my testing, I haven’t found any cases where the system’s behavior changes based on this method’s return value. If you add a view that uses Auto Layout to a view hierarchy using Autoresizing, the system simply converts the entire view hierarchy to Auto Layout. However, future code--including our own code or third-party libraries--may check this value, so we should make sure our classes behave correctly.

Next, when Auto Layout aligns two views, it actually aligns them based on their alignment rectangle--not on their frames. This might not be immediately apparent, since the alignment rectangle is set to the view’s frame by default. Still, if our view has some content that shouldn’t be considered when aligning--a badge icon that sticks out past the view’s regular content, for example, we may want to set the alignment rectangle to a subsection of its frame.

The easiest way to set the alignment rect is to override the view’s alignmentRectInsets method. This returns the UIEdgeInsets that define the offset between the alignment rectangle and the view’s frame. Alternatively, we can override alignmentRectForFrame: and frameForAlignmentRect: methods to convert between the alignment rect and its frame. By default, these methods call alignmentRectInsets, and perform the conversion based on those insets.

Finally, a view can save some or all of its constraints when it is archived. Each constraint has a shouldBeArchived property. By default, this is set to NO, and the constraint is not saved with the view. However, if we want the constraint to be saved, we can simply set its shouldBeArchived property to YES.


There are really three types of problems we can run into when creating constraints. Our constraints could be ambiguous, they could have conflicts, or they could simply be wrong.

Detecting Ambiguous Layouts

A view has an ambiguous layout if there are more than one possible layouts that satisfy all its constraints. Typically ambiguous layouts cause our view to appear in the wrong location, or to have the wrong size. Sometimes the layout may change between one run and the next, or the view may otherwise jump or shift unexpectedly.

Typically this means we need to add additional constraints. As stated earlier, each view needs at least 4 constraints to specify both its position and its size. If you are using inequalities, more constraints are needed.

However, we can also have ambiguous layout if we have conflicting non-required constraints, and if these constraints have the same priority. The system won’t be able to determine which constraint should be fulfilled. In these cases, we have to modify one of the priorities to break the tie.

Also, ambiguous constraints typically come from programmatically defined constraints. The constraints created by Interface Builder should always unambiguously describe your views. You may not like the constraints that Interface Builder chooses, but they shouldn’t be ambiguous.

Detecting and debugging ambiguous layouts is largely a matter of trial and error--however, the system does provide a few tools to help. First, we have a variety of debugging methods. These methods should only be used during debugging. For example, while writing code to explore the layout and determine why our application is not behaving properly.

UIView’s hasAmbiguousLayout is our front line tool. Quite simply, it will return YES if the view has an ambiguous layout. It will return NO otherwise. This provides a quick test. If the layout is ambiguous, we can explore further. If not, then either our constraints are just buggy, or there’s something else wrong with our code.

Next, UIView’s exerciseAmbiguityInLayout will randomly change the view’s frame to another value that also satisfies its constraints. By cycling through several alternates, you should soon get a feel for the missing constraint.

Finally, constraintsAffectingLayoutForAxis: returns an array containing all the constraints affecting the view’s layout along the specified axis. We can then examine these constraints, to get a better feel for the problem.

Remember, if you can find a good place to set a breakpoint, you can call these methods from the debugger’s console:

p (BOOL)[self hasAmbiguousLayout]

Instruments also provides some assistance. There is a Cocoa Layout instrument, that will track any changes to our constraints. The following profile shows a series of rotations. As you can see, with each rotation, the application removed then replaced a number of constraints on the Window.

Cocoa Layout Instrument

Detecting Conflicts

Conflicts are both more serious and easier to detect. Conflicts occur when two (or more) required constraints cannot both be satisfied. Fortunately, the system throws an exception when it detects conflicting constraints.

By default, the system also catches this exception. It logs a warning to the console, then choses one of the constraints to ignore. It will then continue to layout your views.

A sample warning is shown below:

2012-12-28 01:07:09.880 AutoLayoutTest[43733:c07] 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)
  "<NSLayoutConstraint:0x7581490 H:[MyView:0x7580c30(60)]>",
  "<NSLayoutConstraint:0x7581320 H:[MyView:0x7580c30(80)]>"

Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x7581320 H:[MyView:0x7580c30(80)]>

Note: When possible NSLayoutConstraint’s description method uses visual formatting. Where this is not possible, it will use pseudo code to write out the linear equation directly.

In this example, you can see that we’ve set two different constraints specifying the height of this MyView instance. In one case, we set the height to 60 points. In the other, we set it to 80 points. The system then choses to ignore the 80-point constraint and continue to layout the view.

We can set a breakpoint to detect this exception. Either set an exception breakpoint or set a symbolic breakpoint for objc_exception_throw. However, this will only provide useful information for constraints set in a view’s updateConstraints method. Constraints added anywhere else will throw an exception during the next update phase--not at the point when the constraint was added.

Constraints and Core Animation

Before Auto Layout, if we wanted to animate a change in position, we could just modify the view’s frame or center property inside an animation block, as shown below:

    CGRect frame = self.subview.frame;
    CGFloat top = CGRectGetMinY(frame);
    CGFloat left = CGRectGetMinX(frame);
    if (left < CGRectGetWidth(self.view.bounds)) {
        left += 100.0;
    } else {
        left = 0.0;
        top += 100.0;
    frame.origin.x = left;
    frame.origin.y = top;
    [UIView animateWithDuration:0.25 animations:^{

        self.subview.frame = frame;

While this will still move the view, it doesn’t change the constraints. This means the constraints will clobber your new settings during the next layout phase. This may occur immediately after the animation block--or it may occur when the view is rotated, or when some other change is made to the view hierarchy.

To properly animate any changes to a view’s size or position, we need to move away from using the bounds, frame and center properties, and begin modifying the constraints themselves. There are really 3 steps: remove the old constraints, add the new constraints, then call layoutIfNeeded inside an animation block.

Unfortunately, the new code is quite a bit more complex than the old code--and these were a relatively simple set of constraints.

    UIView *view = self.view;
    CGFloat top = self.topMargin.constant;
    CGFloat left = self.leftMargin.constant;
    // Remove Old Constraints
    [view removeConstraint:self.topMargin];
    [view removeConstraint:self.leftMargin];
    if (left < CGRectGetWidth(view.bounds)) {
        left += 100.0;
    } else {
        left = 0.0;
        top += 100.0;
    // Add New Constraints
    self.topMargin =
    [NSLayoutConstraint constraintWithItem:self.subview
    self.leftMargin =
    [NSLayoutConstraint constraintWithItem:self.subview
    [view addConstraint:self.topMargin];
    [view addConstraint:self.leftMargin];
    // Call layoutIfNeeded
    [UIView animateWithDuration:0.25 animations:^{
        [view layoutIfNeeded];

We can also modify existing constraints; however, this has limitations. We can only modify the constraint’s constant property. So the following code would move the subview:

    self.topMargin.constant = top;
    self.leftMargin.constant = left;

Unfortunately, we cannot animate these changes in iOS (OS X could animate it using the animator proxy). If you are feeling really determined, you could produce an animation effect by using an NSTimer to make small incremental changes to these values. However, at that point, it’s probably easier to just remove and replace the whole constraint.


As you can see, Auto Layout gives us considerably more power when it comes to laying out our view hierarchy--but this power comes at a cost. No question, Auto Layout is more complex than Autoresizing, and I often wonder if the system isn’t a bit over-engineered. Yes, it solves a number of really complex problems, but do these solutions pay for the additional complexity?

For example, it can greatly simplify internationalization, since buttons can now automatically adapt their size based on the length of their titles. A well-designed interface should be able to automatically reconfigure itself as you move from one language to another. This avoids the need for separate, language specific layouts.

Still, I’m not sure how well this advantage will play out on the more space-constrained iOS screens. I imagine a number of applications may choose to implement separate layouts for each language, just because it gives them fine control over a highly limited resource.

Having said that, many of the problems people are having with Auto Layout undoubtedly come from their unfamiliarity with it. It is a radical paradigm shift away from the older frame/bounds/center layouts. And, as with all paradigm shifts, it may take some time to get used to.

Auto Layout quickly becomes more useful as you grow more familiar with it. Yes, it can be daunting when you first start out. However, once you get the feel for it, it really isn’t that bad.

If you wish to explore this topic in more detail, I recommend watching the videos from WWDC 2012. There are three videos on Auto Layout: Introduction to Auto Layout for iOS and OS X, Best Practices for Mastering Auto Layout and Auto Layout by Example.

My best recommendation, however, is to just start playing around with it. Build some simple exploratory projects. Play with the constraints that Interface Builder creates, then try to programmatically build your own. The only way to really get comfortable is to get some digital dirt under your fingernails. So, go. Play. And try to have fun.