You are on page 1of 106

Understanding Auto Layout

Auto Layout dynamically calculates the size and position of all the views in your view
hierarchy, based on constraints placed on those views. For example, you can constrain a
button so that it is horizontally centered with an Image view and so that the button’s top
edge always remains 8 points below the image’s bottom. If the image view’s size or
position changes, the button’s position automatically adjusts to match.

This constraint-based approach to design allows you to build user interfaces that
dynamically respond to both internal and external changes.

External Changes
External changes occur when the size or shape of your superview changes. With each
change, you must update the layout of your view hierarchy to best use the available
space. Here are some common sources of external change:

• The user resizes the window (OS X).


• The user enters or leaves Split View on an iPad (iOS).
• The device rotates (iOS).
• The active call and audio recording bars appear or disappear (iOS).
• You want to support different size classes.
• You want to support different screen sizes.

Most of these changes can occur at runtime, and they require a dynamic response from
your app. Others, like support for different screen sizes, represent the app adapting to
different environments. Even through the screen size won’t typically change at runtime,
creating an adaptive interface lets your app run equally well on an iPhone 4S, an iPhone 6
Plus, or even an iPad. Auto Layout is also a key component for supporting Slide Over and
Split Views on the iPad.

Internal Changes
Internal changes occur when the size of the views or controls in your user interface
change.

Here are some common sources of internal change:

• The content displayed by the app changes.


• The app supports internationalization.
• The app supports Dynamic Type (iOS).

When your app’s content changes, the new content may require a different layout than the
old. This commonly occurs in apps that display text or images. For example, a news app
needs to adjust its layout based on the size of the individual news articles. Similarly, a
photo collage must handle a wide range of image sizes and aspect ratios.
Internationalization is the process of making your app able to adapt to different languages,
regions, and cultures. The layout of an internationalized app must take these differences
into account and appear correctly in all the languages and regions that the app supports.

Internationalization has three main effects on layout. First, when you translate your user
interface into a different language, the labels require a different amount of space. German,
for example, typically requires considerably more space than English. Japanese
frequently requires much less.

Second, the format used to represent dates and numbers can change from region to
region, even if the language does not change. Although these changes are typically more
subtle than the language changes, the user interface still needs to adapt to the slight
variation in size.

Third, changing the language can affect not just the size of the text, but the organization of
the layout as well. Different languages use different layout directions. English, for
example, uses a left-to-right layout direction, and Arabic and Hebrew use a right-to-left
layout direction. In general, the order of the user interface elements should match the
layout direction. If a button is in the bottom-right corner of the view in English, it should be
in the bottom left in Arabic.

Finally, if your iOS app supports dynamic type, the user can change the font size used in
your app. This can change both the height and the width of any textual elements in your
user interface. If the user changes the font size while your app is running, both the fonts
and the layout must adapt.

Auto Layout Versus Frame-Based Layout


There are three main approaches to laying out a user interface. You can programmatically
lay out the user interface, you can use autoresizing masks to automate some of the
responses to external change, or you can use Auto Layout.

Traditionally, apps laid out their user interface by programmatically setting the frame for
each view in a view hierarchy. The frame defined the view’s origin, height, and width in the
superview’s coordinate system.
To lay out your user interface, you had to calculate the size and position for every view in
your view hierarchy. Then, if a change occurred, you had to recalculate the frame for all
the effected views.

In many ways, programmatically defining a view’s frame provides the most flexibility and
power. When a change occurs, you can literally make any change you want. Yet because
you must also manage all the changes yourself, laying out a simple user interface requires
a considerable amount of effort to design, debug, and maintain. Creating a truly adaptive
user interface increases the difficulty by an order of magnitude.

You can use autoresizing masks to help alleviate some of this effort. An autoresizing mask
defines how a view’s frame changes when its superview’s frame changes. This simplifies
the creation of layouts that adapt to external changes.

However, autoresizing masks support a relatively small subset of possible layouts. For
complex user interfaces, you typically need to augment the autoresizing masks with your
own programmatic changes. Additionally, autoresizing masks adapt only to external
changes. They do not support internal changes.

Although autoresizing masks are just an iterative improvement on programmatic layouts,


Auto Layout represents an entirely new paradigm. Instead of thinking about a view’s
frame, you think about its relationships.

Auto Layout defines your user interface using a series of constraints. Constraints typically
represent a relationship between two views. Auto Layout then calculates the size and
location of each view based on these constraints. This produces layouts that dynamically
respond to both internal and external changes.

The logic used to design a set of constraints to create specific behaviors is very different
from the logic used to write procedural or object-oriented code. Fortunately, mastering
Auto Layout is no different from mastering any other programming task. There are two
basic steps: First you need to understand the logic behind constraint-based layouts, and
then you need to learn the API. You’ve successfully performed these steps when learning
other programming tasks. Auto Layout is no exception.

The rest of this guide is designed to help ease your transition to Auto Layout. The Auto
Layout Without Constraints chapter describes a high-level abstraction that simplifies the
creation of Auto Layout backed user interfaces. The Anatomy of a Constraint chapter
provides the background theory you need to understand to successfully interact with Auto
Layout on your own. Working with Constraints in Interface Builder describes the tools for
designing Auto Layout, and the Programmatically Creating Constraints and Auto Layout
Cookbook chapters describe the API in detail. Finally, the Auto Layout Cookbook presents
a wide range of sample layouts of varying levels of complexity, you can study and use in
your own projects, and Debugging Auto Layout offers advice and tools for fixing things if
anything goes wrong.
Auto Layout Without Constraints
Stack views provide an easy way to leverage the power of Auto Layout without introducing
the complexity of constraints. A single stack view defines a row or column of user interface
elements. The stack view arranges these elements based on its properties.

• axis: (UIStackView only) defines the stack view’s orientation, either vertical or
horizontal.
• orientation: (NSStackView only) defines the stack view’s orientation, either vertical
or horizontal.
• distribution: defines the layout of the views along the axis.

• alignment: defines the layout of the views perpendicular to the stack view’s axis.

• spacing: defines the space between adjacent views.

To use a stack view, in Interface Builder drag either a vertical or horizontal stack view onto
the canvas. Then drag out the content and drop it into the stack.

If an object has an intrinsic content size, it appears in the stack at that size. If it does not
have an intrinsic content size, Interface Builder provides a default size. You can resize the
object, and Interface Builder adds constraints to maintain its size.

To further fine-tune the layout, you can modify the stack view’s properties using the
Attributes inspector. For example, the following example uses an 8-point spacing and a
Fills Equally distribution.

The stack view also bases its layout on the arranged views’ content-hugging and
compression-resistance priorities. You can modify these using the Size inspector.

NOTE

You can further modify the layout by adding constraints directly to the arranged views;
however, you want to avoid any possible conflicts: As a general rule of thumb, if a view’s
size defaults back to its intrinsic content size for a given dimension, you can safely add a
constraint for that dimension. For more information on conflicting constraints, see
Unsatisfiable Layouts.

Additionally, you can nest stack views inside other stack views to build more complex
layouts.
In general, use stack views to manage as much of your layout as possible. Resort to
creating constraints only when you cannot achieve your goals with stack views alone.

For more information on using stack views, see UIStackView Class Reference or
NSStackView Class Reference.

NOTE

Although the creative use of nested stack views can produce complex user interfaces, you
cannot completely escape the need for constraints. At a bare minimum, you always need
constraints to define the position (and possibly the size) of the outermost stack.
Anatomy of a Constraint
The layout of your view hierarchy is defined as a series of linear equations. Each
constraint represents a single equation. Your goal is to declare a series of equations that
has one and only one possible solution.

A sample equation is shown below.

This constraint states that the red view’s leading edge must be 8.0 points after the blue
view’s trailing edge. Its equation has a number of parts:

• Item 1. The first item in the equation—in this case, the red view. The item must be
either a view or a layout guide.

• Attribute 1. The attribute to be constrained on the first item—in this case, the red
view’s leading edge.
• Relationship. The relationship between the left and right sides. The relationship can
have one of three values: equal, greater than or equal, or less than or equal. In this
case, the left and right side are equal.

• Multiplier. The value of attribute 2 is multiplied by this floating point number. In this
case, the multiplier is 1.0.

• Item 2. The second item in the equation—in this case, the blue view. Unlike the first
item, this can be left blank.
• Attribute 2. The attribute to be constrained on the second item—in this case, the
blue view’s trailing edge. If the second item is left blank, this must be Not an
Attribute.

• Constant. A constant, floating-point offset—in this case, 8.0. This value is added to
the value of attribute 2.

Most constraints define a relationship between two items in our user interface. These
items can represent either views or layout guides. Constraints can also define the
relationship between two different attributes of a single item, for example, setting an
aspect ratio between an item’s height and width. You can also assign constant values to
an item’s height or width. When working with constant values, the second item is left
blank, the second attribute is set to Not An Attribute, and the multiplier is set to 0.0.
Auto Layout Attributes
In Auto Layout, the attributes define a feature that can be constrained. In general, this
includes the four edges (leading, trailing, top, and bottom), as well as the height, width,
and vertical and horizontal centers. Text items also have one or more baseline attributes.

For the complete list of attributes, see the NSLayoutAttribute enum.

NOTE

Although both OS X and iOS use the NSLayoutAttribute enum, they define slightly
different sets of values. To see the full list of attributes, be sure you are looking at the
correct platform’s documentation.

Sample Equations
The wide range of parameters and attributes available to these equations lets you create
many different types of constraints. You can define the space between views, align the
edge of views, define the relative size of two views, or even define a view’s aspect ratio.
However, not all attributes are compatible.

There are two basic types of attributes. Size attributes (for example, Height and Width)
and location attributes (for example, Leading, Left, and Top). Size attributes are used to
specify how large an item is, without any indication of its location. Location attributes are
used to specify the location of an item relative to something else. However, they carry no
indication of the item’s size.

With these differences in mind, the following rules apply:

• You cannot constrain a size attribute to a location attribute.


• You cannot assign constant values to location attributes.
• You cannot use a nonidentity multiplier (a value other than 1.0) with location
attributes.

• For location attributes, you cannot constrain vertical attributes to horizontal


attributes.
• For location attributes, you cannot constrain Leading or Trailing attributes to Left or
Right attributes.

For example, setting an item’s Top to the constant value 20.0 has no meaning without
additional context. You must always define an item’s location attributes in relation to other
items, for example, 20.0 points below the superview’s Top. However, setting an item’s
Height to 20.0 is perfectly valid. For more information, see Interpreting Values.

Listing 3-1 shows sample equations for a variety of common constraints.

NOTE

All the example equations in this chapter are presented using pseudocode. To see real
constraints using real code, see Programmatically Creating Constraints or Auto Layout
Cookbook.

Listing 3-1 Sample equations for common constraints

1 // Setting a constant height


2 View.height = 0.0 * NotAnAttribute + 40.0
3
4 // Setting a fixed distance between two buttons
5 Button_2.leading = 1.0 * Button_1.trailing + 8.0
6
7 // Aligning the leading edge of two buttons
8 Button_1.leading = 1.0 * Button_2.leading + 0.0
9
10 // Give two buttons the same width
11 Button_1.width = 1.0 * Button_2.width + 0.0
12
13 // Center a view in its superview
14 View.centerX = 1.0 * Superview.centerX + 0.0
15 View.centerY = 1.0 * Superview.centerY + 0.0
16
17 // Give a view a constant aspect ratio
18 View.height = 2.0 * View.width + 0.0

Equality, Not Assignment


It’s important to note that the equations shown in Note represent equality, not assignment.

When Auto Layout solves these equations, it does not just assign the value of the right
side to the left. Instead, it calculates the value for both attribute 1 and attribute 2 that
makes the relationship true. This means we can often freely reorder the items in the
equation. For example, the equations in Listing 3-2 are identical to their counterparts in
Note.

Listing 3-2 Inverted equations

1 // Setting a fixed distance between two buttons


2 Button_1.trailing = 1.0 * Button_2.leading - 8.0
3
4 // Aligning the leading edge of two buttons
5 Button_2.leading = 1.0 * Button_1.leading + 0.0
6
7 // Give two buttons the same width
8 Button_2.width = 1.0 * Button.width + 0.0
9
10 // Center a view in its superview
11 Superview.centerX = 1.0 * View.centerX + 0.0
12 Superview.centerY = 1.0 * View.centerY + 0.0
13
14 // Give a view a constant aspect ratio
15 View.width = 0.5 * View.height + 0.0

NOTE

When reordering the items, make sure you invert the multiplier and the constant. For
example, a constant of 8.0 becomes -8.0. A multiplier of 2.0 becomes 0.5. Constants of
0.0 and multipliers of 1.0 remain unchanged.

You will find that Auto Layout frequently provides multiple ways to solve the same
problem. Ideally, you should choose the solution that most clearly describes your intent.
However, different developers will undoubtedly disagree about which solution is best.
Here, being consistent is better than being right. You will experience fewer problems in the
long run if you choose an approach and always stick with it. For example, this guide uses
the following rules of thumb:

1. Whole number multipliers are favored over fractional multipliers.


2. Positive constants are favored over negative constants.
3. Wherever possible, views should appear in layout order: leading to trailing, top to
bottom.

Creating Nonambiguous, Satisfiable Layouts


When using Auto Layout, the goal is to provide a series of equations that have one and
only one possible solution. Ambiguous constraints have more than one possible solution.
Unsatisfiable constraints don’t have valid solutions.
In general, the constraints must define both the size and the position of each view.
Assuming the superview’s size is already set (for example, the root view of a scene in
iOS), a nonambiguous, satisfiable layout requires two constraints per view per dimension
(not counting the superview). However, you have a wide range of options when it comes
to choosing which constraints you want to use. For example, the following three layouts all
produce nonambiguous, satisfiable layouts (only the horizontal constraints are shown):

• The first layout constrains the view’s leading edge relative to its superview’s leading
edge. It also gives the view a fixed width. The position of the trailing edge can then
be calculated based on the superview’s size and the other constraints.
• The second layout constrains the view’s leading edge relative to its superview’s
leading edge. It also constrains the view’s trailing edge relative to the superview’s
trailing edge. The view’s width can then be calculated based on the superview’s size
and the other constraints.

• The third layout constrains the view’s leading edge relative to its superview’s leading
edge. It also center aligns the view and superview. Both the width and trailing edge’s
position can then be calculated based on the superview’s size and the other
constraints.

Notice that each layout has one view and two horizontal constraints. In each case, the
constraints fully define both the width and the horizontal position of the view. That means
all of the layouts produce a nonambiguous, satisfiable layout along the horizontal axis.
However, these layouts are not equally useful. Consider what happens when the
superview’s width changes.

In the first layout, the view’s width does not change. Most of the time, this is not what you
want. In fact, as a general rule, you should avoid assigning constant sizes to views. Auto
Layout is designed to create layouts that dynamically adapt to their environment.
Whenever you give a view a fixed size, you short circuiting that ability.

It may not be obvious, but the second and third layouts produce identical behaviors: They
both maintain a fixed margin between the view and its superview as the superview’s width
changes. However, they are not necessarily equal. In general, the second example is
easier to understand, but the third example may be more useful, especially when you are
center aligning a number of items. As always, choose the best approach for your
particular layout.

Now consider something a little more complicated. Imagine you want to display two views,
side by side, on an iPhone. You want to make sure that they have a nice margin on all
sides and that they always have the same width. They should also correctly resize as the
device rotates.

The following illustrations show the views, in portrait and landscape orientation:

So what should these constraints look like? The following illustration shows one
straightforward solution:
The above solution uses the following constraints:

1 // Vertical Constraints
2 Red.top = 1.0 * Superview.top + 20.0
3 Superview.bottom = 1.0 * Red.bottom + 20.0
4 Blue.top = 1.0 * Superview.top + 20.0
5 Superview.bottom = 1.0 * Blue.bottom + 20.0
6
7 // Horizontal Constraints
8 Red.leading = 1.0 * Superview.leading + 20.0
9 Blue.leading = 1.0 * Red.trailing + 8.0
10 Superview.trailing = 1.0 * Blue.trailing + 20.0
11 Red.width = 1.0 * Blue.width + 0.0

Following the earlier rule of thumb, this layout has two views, four horizontal constraints,
and four vertical constraints. While this isn’t an infallible guide, it is a quick indication that
you’re on the right track. More importantly, the constraints uniquely specify both the size
and the location of both of the views, producing a nonambiguous, satisfiable layout.
Remove any of these constraints, and the layout becomes ambiguous. Add additional
constraints, and you risk introducing conflicts.

Still, this is not the only possible solution. Here is an equally valid approach:

Instead of pinning the top and bottom of the blue box to its superview, you align the top of
the blue box with the top of the red box. Similarly, you align the bottom of the blue box
with the bottom of the red box. The constraints are shown below.
1 // Vertical Constraints
2 Red.top = 1.0 * Superview.top + 20.0
3 Superview.bottom = 1.0 * Red.bottom + 20.0
4 Red.top = 1.0 * Blue.top + 0.0
5 Red.bottom = 1.0 * Blue.bottom + 0.0
6
7 //Horizontal Constraints
8 Red.leading = 1.0 * Superview.leading + 20.0
9 Blue.leading = 1.0 * Red.trailing + 8.0
10 Superview.trailing = 1.0 * Blue.trailing + 20.0
11 Red.width = 1.0 * Blue.width + 0.0

The example still has two views, four horizontal constraints, and four vertical constraints. It
still produces a nonambiguous, satisfiable layout.

BUT WHICH IS BETTER?

These solutions both produce valid layouts. So which is better?

Unfortunately, it is virtually impossible to objectively prove that one approach is strictly


superior to the other. Each has its own strengths and weaknesses.

The first solution is more robust when a view is removed. Removing a view from the view
hierarchy also removes all the constraints that reference that view. So, if you remove the
red view, the blue view is left with three constraints holding it in place. You need to add
only a single constraint and you have a valid layout again. In the second solution,
removing the red view would leave the blue view with only a single constraint.

On the other hand, in the first solution, If you want the top and bottom of the views to align,
you must make sure their top and bottom constraints use the same constant value. If you
change one constant, you must remember to change the other as well.

Constraint Inequalities
So far, all of the samples have shown constraints as equalities, but this is only part of the
story. Constraints can represent inequalities as well. Specifically, the constraint’s
relationship can be equal to, greater than or equal to, or less than or equal to.

For example, you can use constraints to define the minimum or maximum size for a view
(Listing 3-3).

Listing 3-3 Assigning a minimum and maximum size

1 // Setting the minimum width


2 View.width >= 0.0 * NotAnAttribute + 40.0
3
4 // Setting the maximum width
5 View.width <= 0.0 * NotAnAttribute + 280.0

As soon as you start using inequalities, the two constraints per view per dimension rule
breaks down. You can always replace a single equality relationship with two inequalities.
In Listing 3-4, the single equal relationship and the pair of inequalities produce the same
behavior.

Listing 3-4 Replacing a single equal relationship with two inequalities

1 // A single equal relationship


2 Blue.leading = 1.0 * Red.trailing + 8.0
3
4 // Can be replaced with two inequality relationships
5 Blue.leading >= 1.0 * Red.trailing + 8.0
6 Blue.leading <= 1.0 * Red.trailing + 8.0

The inverse is not always true, because two inequalities are not always equivalent to a
single equals relationship. For example, the inequalities in Listing 3-3 limit the range of
possible values for the view’s width—but by themselves, they do not define the width. You
still need additional horizontal constraints to define the view’s position and size within this
range.

Constraint Priorities
By default, all constraints are required. Auto Layout must calculate a solution that satisfies
all the constraints. If it cannot, there is an error. Auto Layout prints information about the
unsatisfiable constraints to the console, and chooses one of the constraints to break. It
then recalculates the solution without the broken constraint. For more information, see
Unsatisfiable Layouts.

You can also create optional constraints. All constraints have a priority between 1 and
1000. Constraints with a priority of 1000 are required. All other constraints are optional.

When calculating solutions, Auto Layout attempts to satisfy all the constraints in priority
order from highest to lowest. If it cannot satisfy an optional constraint, that constraint is
skipped and it continues on to the next constraint.

Even if an optional constraint cannot be satisfied, it can still influence the layout. If there is
any ambiguity in the layout after skipping the constraint, the system selects the solution
that comes closest to the constraint. In this way, unsatisfied optional constraints act as a
force pulling views towards them.

Optional constraints and inequalities often work hand-in-hand. For example, in Listing 3-4
you can provide different priorities for the two inequalities. The greater-than-or-equal
relationship could be required (priority of 1000), and the less-than-or-equal relationship
has a lower priority (priority 250). This means that the blue view cannot be closer than 8.0
points from the red. However, other constraints could pull it farther away. Still, the optional
constraint pulls the blue view towards the red view, ensuring that it is as close as possible
to the 8.0-point spacing, given the other constraints in the layout.
NOTE

Don’t feel obligated to use all 1000 priority values. In fact, priorities should general cluster
around the system-defined low (250), medium (500), high (750), and required (1000)
priorities. You may need to make constraints that are one or two points higher or lower
than these values, to help prevent ties. If you’re going much beyond that, you probably
want to reexamine your layout’s logic.

For a list of the predefined constraint constants on iOS, see the UILayoutPriority enum.
For OS X, see the Layout Priorities constants.

Intrinsic Content Size


So far, all of the examples have used constraints to define both the view’s position and its
size. However, some views have a natural size given their current content. This is referred
to as their intrinsic content size. For example, a button’s intrinsic content size is the size of
its title plus a small margin.

Not all views have an intrinsic content size. For views that do, the intrinsic content size
can define the view’s height, its width, or both. Some examples are listed in Table 3-1.

Table 3-1 Intrinsic content size for common controls

View Intrinsic content size

UIView and NSView No intrinsic content size.

Defines only the width (iOS).


Sliders Defines the width, the height, or both—
depending on the slider’s type (OS X).

Labels, buttons, switches, and text


Defines both the height and the width.
fields

Text views and image views Intrinsic content size can vary.

The intrinsic content size is based on the view’s current content. A label or button’s
intrinsic content size is based on the amount of text shown and the font used. For other
views, the intrinsic content size is even more complex. For example, an empty image view
does not have an intrinsic content size. As soon as you add an image, though, its intrinsic
content size is set to the image’s size.

A text view’s intrinsic content size varies depending on the content, on whether or not it
has scrolling enabled, and on the other constraints applied to the view. For example, with
scrolling enabled, the view does not have an intrinsic content size. With scrolling disabled,
by default the view’s intrinsic content size is calculated based on the size of the text
without any line wrapping. For example, if there are no returns in the text, it calculates the
height and width needed to layout the content as a single line of text. If you add
constraints to specify the view’s width, the intrinsic content size defines the height
required to display the text given its width.

Auto Layout represents a view’s intrinsic content size using a pair of constraints for each
dimension. The content hugging pulls the view inward so that it fits snugly around the
content. The compression resistance pushes the view outward so that it does not clip the
content.

These constraints are defined using the inequalities shown in Listing 3-5. Here, the
IntrinsicHeight and IntrinsicWidth constants represent the height and width values
from the view’s intrinsic content size.

Listing 3-5 Compression-Resistance and Content-Hugging equations

1 // Compression Resistance
2 View.height >= 0.0 * NotAnAttribute + IntrinsicHeight
3 View.width >= 0.0 * NotAnAttribute + IntrinsicWidth
4
5 // Content Hugging
6 View.height <= 0.0 * NotAnAttribute + IntrinsicHeight
7 View.width <= 0.0 * NotAnAttribute + IntrinsicWidth

Each of these constraints can have its own priority. By default, views use a 250 priority for
their content hugging, and a 750 priority for their compression resistance. Therefore, it’s
easier to stretch a view than it is to shrink it. For most controls, this is the desired
behavior. For example, you can safely stretch a button larger than its intrinsic content size;
however, if you shrink it, its content may become clipped. Note that Interface Builder may
occasionally modify these priorities to help prevent ties. For more information, see Setting
Content-Hugging and Compression-Resistance Priorities.

Whenever possible, use the view’s intrinsic content size in your layout. It lets your layout
dynamically adapt as the view’s content changes. It also reduces the number of
constraints you need to create a nonambiguous, nonconflicting layout, but you will need to
manage the view’s content-hugging and compression-resistance (CHCR) priorities. Here
are some guidelines for handling intrinsic content sizes:

• When stretching a series of views to fill a space, if all the views have an identical
content-hugging priority, the layout is ambiguous. Auto Layout doesn’t know which
view should be stretched.
A common example is a label and text field pair. Typically, you want the text field to
stretch to fill the extra space while the label remains at its intrinsic content size. To
ensure this, make sure the text field’s horizontal content-hugging priority is lower
than the label’s.
In fact, this example is so common that Interface Builder automatically handles it for
you, setting the content-hugging priority for all labels to 251. If you are
programmatically creating the layout, you need to modify the content-hugging
priority yourself.
• Odd and unexpected layouts often occur when views with invisible backgrounds
(like buttons or labels) are accidentally stretched beyond their intrinsic content size.
The actual problem may not be obvious, because the text simply appears in the
wrong location. To prevent unwanted stretching, increase the content-hugging
priority.
• Baseline constraints work only with views that are at their intrinsic content height. If
a view is vertically stretched or compressed, the baseline constraints no longer align
properly.

• Some views, like switches, should always be displayed at their intrinsic content size.
Increase their CHCR priorities as needed to prevent stretching or compressing.
• Avoid giving views required CHCR priorities. It’s usually better for a view to be the
wrong size than for it to accidentally create a conflict. If a view should always be its
intrinsic content size, consider using a very high priority (999) instead. This
approach generally keeps the view from being stretched or compressed but still
provides an emergency pressure valve, just in case your view is displayed in an
environment that is bigger or smaller than you expected.

Intrinsic Content Size Versus Fitting Size


The intrinsic content size acts as an input to Auto Layout. When a view has an intrinsic
content size, the system generates constraints to represent that size and the constraints
are used to calculate the layout.

The fitting size, on the other hand, is an output from the Auto Layout engine. It is the size
calculated for a view based on the view’s constraints. If the view lays out its subviews
using Auto Layout, then the system may be able to calculate a fitting size for the view
based on its content.

The stack view is a good example. Barring any other constraints, the system calculates
the stack view’s size based on its content and attributes. In many ways, the stack view
acts as if it had an intrinsic content size: You can create a valid layout using only a single
vertical and a single horizontal constraint to define its position. But its size is calculated by
Auto Layout—it is not an input into Auto Layout. Setting the stack view’s CHCR priorities
has no effect, because the stack view does not have an intrinsic content size.

If you need to adjust the stack view’s fitting size relative to items outside the stack view,
either create explicit constraints to capture those relationships or modify the CHCR
priorities of the stack’s contents relative to the items outside the stack.
Interpreting Values
Values in Auto Layout are always in points. However, the exact meaning of these
measurements can vary depending on the attributes involved and the view’s layout
direction.

Auto Layout Attributes Value Notes

These attributes can be assigned constant


Height values or combined with other Height and
The size of the view.
Width Width attributes. These values cannot be
negative.

Top These attributes can be combined only with


The values increase as you move down the
Bottom Center Y, Top, Bottom, and Baseline
screen.
Baseline attributes.

The values increase as you move towards


the trailing edge. For a left-to-right layout
Leading These attributes can be combined only with
directions, the values increase as you move
Trailing Leading, Trailing, or Center X attributes.
to the right. For a right-to-left layout direction,
the values increase as you move left.

These attributes can be combined only with


Left, Right, and Center X attributes.
Avoid using Left and Right attributes. Use
Leading and Trailing instead. This allows the
layout to adapt to the view’s reading
direction.
By default the reading direction is determined
based on the current language set by the
Left The values increase as you move to the
user. However, you can override this where
Right right.
necessary. In iOS, set the
semanticContentAttribute property on
the view holding the constraint (the nearest
common ancestor of all views affected by the
constraint) to specify whether the content’s
layout should be flipped when switching
between left-to-right and right-to-left
languages.

Center X can be combined with Center X,


Center X The interpretation is based on the other Leading, Trailing, Right, and Left attributes.
Center Y attribute in the equation. Center Y can be combined with Center Y,
Top, Bottom, and Baseline attributes.
Working with Constraints in Interface Builder
There are three main options for setting up Auto Layout constraints in Interface Builder:
You can control-drag between views, you can use the Pin and Align tools, and you can let
Interface Builder set up the constraints for you and then edit or modify the results. Each of
these approaches has its own set of strengths and weaknesses. Most developers find that
they prefer one approach over the others; however, being familiar with all three
approaches lets you quickly switch between tools based on the task at hand.

For all three options, start by dragging your views and controls from the Object library onto
the scene. Resize and position them as needed. When you place a view on the canvas,
Interface Builder automatically creates a set of prototyping constraints that define the
view’s current size and position relative to the upper left corner.

The app can build and run with the prototyping constraints. Use these constraints to
quickly visualize and test a user interface, but then replace the implicit constraints with
your own explicit constraints. Never ship an app with prototyping constraints.

As soon as you create your first constraint, the system removes all the prototyping
constraints from the views referred to by the constraint. Without the prototyping
constraints, your layout no longer has enough constraints to uniquely size and position all
the views. It becomes an ambiguous layout. The affected constraints suddenly appear in
red, and Xcode generates a number of warnings.

Don’t panic. Just keep adding your constraints until your layout is complete. As soon as
you add one constraint, you are responsible for adding all the constraints needed to
create a nonambiguous, satisfiable layout.

For more information on fixing layout warnings and errors, see Debugging Auto Layout.

Control-Dragging Constraints
To create a constraint between two views, Control-click one of the views and drag to the
other.

When you release the mouse, Interface Builder displays a HUD menu with a list of
possible constraints.
Interface Builder intelligently selects the set of constraints based on the items you are
constraining and the direction of your drag gesture. If you drag more or less horizontally,
you get options to set the horizontal spacing between the views, and options to vertically
align the views. If you drag more or less vertically, you get options to set the vertical
spacing, and options to align the views horizontally. Both gestures may include other
options (such as setting the view’s relative size).

NOTE

You can use the Control-drag gesture both on items in the canvas and on icons in the
scene’s document outline. This is often useful when trying to draw constraints to hard-to-
find items, like the top or bottom layout guides. When dragging to or from the document
outline, Interface Builder does not filter the list of possible constraints based on the
gesture’s direction.

Interface Builder creates the constraints based on the views’ current frames. Therefore,
you need to position the views carefully before you draw the constraints. If you line up the
views based on Interface Builder’s guidelines, you should end up with a reasonable set of
constraints. If necessary, you can always edit the constraints afterward.

Control-dragging provides a very quick way to set a constraint; however, because the
constraint’s values are inferred from the scene’s current layout, it is easy to end up off by
a point. If you want finer control, review and edit the constraints after you create them, or
use the Pin and Align tools.

For more information on Control-dragging constraints, see Adding Layout Constraints by


Control-Dragging in Auto Layout Help.

Using the Stack, Align, Pin and Resolve Tools


Interface Builder provides four Auto Layout tools in the bottom-right corner of the Editor
window. These are the Stack, Align, Pin, and Resolve Auto Layout Issues tools.
Use the Pin and Align tools when you want fine control when making constraints or when
you want to make multiple constraints at once. As an added advantage, when you use
these tools, you don’t need to precisely place your views before creating the constraint.
Instead, you can roughly set the relative position of the views, add your constraints, and
then update the frames. This lets Auto Layout calculate the correct positions for you.

Stack Tool
The Stack tool allows you to quickly create a stack view. Select one or more items in your
layout, and then click on the Stack tool. Interface Builder embeds the selected items in a
stack view and resizes the stack to its current fitting size based on its contents.

NOTE

The system infers the stack’s axis and alignment from the initial relative position of the
views. You can modify the axis and alignment (and set the distribution and spacing) using
the Attributes inspector.

Align Tool
The Align tool lets you quickly align items in your layout. Select the items you want to
align, and then click the Align tool. Interface Builder presents a popover view containing a
number of possible alignments.

Select the options for aligning the selected views, and click the Add Constraints button.
Interface Builder creates the constraints needed to ensure those alignments. By default,
the constraints do not have any offset (the edges or centers are aligned with each other)
and none of the frames are updated when the constraints are added. You can change any
of these settings before creating the constraints.

You typically select two or more views before using the Align tool. However, the
Horizontally in Container or Vertically in Container constraints can be added to a single
view. You can use the popover to create any number of constraints at once—though it
rarely makes sense to create more than one or two at a time.
For more information, see Adding Auto Layout Constraints with the Pin and Align Tools in
Auto Layout Help.

Pin Tool
The Pin tool lets you quickly define a view’s position relative to its neighbors or quickly
define its size. Select the item whose position or size you want to pin, and click the Pin
tool. Interface Builder presents a popover view containing a number of options.

The top portion of the popover lets you pin the selected item’s Leading, Top, Trailing, or
Bottom edge to its nearest neighbor. The associated number indicates the current spacing
between the items in the canvas. You can type in a custom spacing, or you can click the
disclosure triangle to set which view it should be constrained to or to select the standard
spacing. The “Constrain to margins” checkbox determines whether constraints to the
superview use the superview’s margins or its edges.

The lower portion of the popover lets you set the item’s width or height. The Width and
Height constraints default to the current canvas size, though you can type in different
values. The Aspect Ratio constraint also uses the item’s current aspect ratio; however, if
you want to change this ratio, you need to review and edit the constraint after creating it.

Typically, you select a single view to pin; however, you can select two or more views and
give them equal widths or equal heights. You can also create multiple constraints at once,
or you can update the frames as you add the constraints. After you’ve set the options you
want, click the Add Constraints button to create your constraints.

For more information, see Adding Auto Layout Constraints with the Pin and Align Tools in
Auto Layout Help.

Resolve Auto Layout Issues Tool


The Resolve Auto Layout Issues tool provides a number of options for fixing common
Auto Layout issues. The options in the upper half of the menu affect only the currently
selected views. The options in the bottom half affect all views in the scene.

You can use this tool to update the views’ frames based on the current constraints, or you
can update the constraints based on the views’ current location in the canvas. You can
also add missing constraints, clear constraints, or reset the views to a set of constraints
recommended by Interface Builder.

The commands to add or reset constraints are discussed in greater detail in Letting
Interface Builder Create Constraints.

Letting Interface Builder Create Constraints


Interface Builder can create some or all of the constraints for you. When using this
approach, Interface Builder attempts to infer the best constraints given the view’s current
size and position in the canvas. Be sure to position your views carefully—small
differences in spacing can result in significantly different layouts.

To let Interface Builder create all the constraints, click Resolve Auto Layout Issues tool >
Reset to Suggested Constraints. Interface Builder creates all the required constraints for
the selected views (or for all the views in the scene).

Alternatively, you can add a few constraints yourself, and then click the Resolve Auto
Layout Issues tool > Add Missing Constraints. This option adds the constraints needed to
have a nonambiguous layout. Again, you can add constraints either to the selected view
or to all the views in the scene.

This approach lets you rapidly build a nonambiguous, satisfiable layout, but unless the
user interface is straightforward, the resulting layout may not behave the way you want.
Always test the user interface and modify the constraints until you get the intended
results.

Finding and Editing Constraints


After you’ve added a constraint, you need to be able to find it, view it, and edit it. There
are a number of options for accessing the constraints. Each option offers a unique method
of organizing and presenting the constraints.

Viewing Constraints in the Canvas


The editor displays all the constraints affecting the currently selected view as colored lines
on the canvas. The shape, stroke type, and line color can tell you a lot about the current
state of the constraint.

• I-bars (lines with T-shaped end-caps). I-bars show the size of a space. This space
can be either the distance between two items, or the height or width of an item.
• Plain lines (straight lines with no end-caps). Plain lines show where edges align.
For example, Interface Builder uses simple lines when aligning the leading edge of
two or more views. These lines can also be used to connect items that have a 0-
point space between them.
• Solid Lines. Solid lines represent required constraints (priority = 1000).
• Dashed Lines. Dashed lines represent optional constraints (priority < 1000).
• Red Lines. One of the items affected by this constraint has an error. Either the item
has an ambiguous layout, or its layout is not satisfiable. For more information, see
the issues navigator or the disclosure arrow in Interface Builder’s outline view.
• Orange Lines. Orange lines indicate that the frame of one of the items affected by
this constraint is not in the correct position based on the current set of constraints.
Interface Builder also shows the calculated position for the frame as a dashed
outline. You can move the item to its calculated position using the Resolve Auto
Layout Issues tool > Update Frames command.
• Blue Lines. The items affected by the constraint have a nonambiguous, satisfiable
layout, and the item’s frame is in the correct position as calculated by the Auto
Layout engine.
• Equal Badges. Interface Builder shows constraints that give two items an equal
width or an equal height as a separate bar for each item. Both bars are tagged with
a blue badge containing an equal (=) sign inside.

• Greater-than-or-equal and less-than-or-equal badges. Interface Builder marks all


constraints representing greater-than-or-equal-to and less-than-or-equal-to
relationships with a small blue badge with a >= or <= symbol inside.
Listing Constraints in the Document Outline
Interface Builder lists all the constraints in the document outline, grouping them under the
view that holds them. Constraints are held by the closest view that contains both items in
the constraint. For this calculation, each view contains itself and all its subviews, and the
top and bottom layout guides are contained by the scene’s root view.

Even though constraints could be spread around the outline, most constraints end up
under the scene’s root view. If you want to make sure you’ve found all the constraints,
expand the entire view hierarchy.

The constraints are listed using pseudocode. These listings are often long, and they
frequently start with a similar set of views, so you may have to increase the width of the
outline before you can see meaningful information. Selecting a constraint in the outline
highlights that constraint in the canvas. Use this feature to help you quickly identify the
constraint you want to examine.

For simple scenes, the outline is a great place to glance over all the scene’s constraints.
However, as the layout becomes more complex, it quickly becomes hard to find specific
constraints. You are often better off examining the constraints one view at a time—either
by selecting the view in the canvas or by examining the view in the Size inspector.
Finding Constraints in the Size Inspector
The Size inspector lists all the constraints affecting the currently selected view. Required
constraints appear with a solid outline, and optional constraints appear with a dashed
outline. The description lists important information about the constraint. It always includes
the affected attribute and the other item in the constraint. It may also include the
relationship, the constant value, and the multiplier or ratio.

The diagram at the top of the above screenshot shows which attributes are affected by
constraints. You can filter the list of constraints by selecting one or more of the diagram’s
attributes. The list then shows only those constraints affecting the selected attributes.

For more information, see Viewing the Complete List of Layout Constraints for an Item in
Auto Layout Help.

Examining and Editing Constraints


When you select a constraint either in the canvas or in the document outline, the Attribute
inspector shows all of the constraint’s attributes. This includes all the values from the
constraint equation: the first item, the relation, the second item, the constant, and the
multiplier. The Attribute inspector also shows the constraint’s priority and its identifier.
NOTE

The constraint’s identifier property lets you provide a descriptive name so that you can
more easily identify the constraint in console logs and other debugging tasks.

You can also mark the constraint as a placeholder. These constraints exist only at design
time. They are not included in the layout when the app runs. You typically add placeholder
constraints when you plan to dynamically add constraints at runtime. By temporarily
adding the constraints needed to create a nonambiguous, satisfiable layout, you clear out
any warnings or errors in Interface Builder.

You can freely modify the Constant, Priority, Multiplier, Relation, Identifier, and Placeholder
attributes. For the first and second item, however, your options are more limited. You can
swap the first and second item (inverting the multiplier and constant, as needed). You can
also change the item’s attribute, but you cannot change the item itself. If you need to
move the constraint to a completely different item, delete the constraint and replace it with
a new constraint.

Some editing is also possible directly from the Size inspector. Clicking the Edit button in
any of the constraints brings up a popover where you can change the constraint’s
relationship, constant, priority, or multiplier. To make additional changes, double-click the
constraint to select it and open it in the Attribute inspector.

For more information, see Editing Auto Layout Constraints in Auto Layout Help.

Setting Content-Hugging and Compression-Resistance


Priorities
To set a view’s content-hugging and compression-resistance priorities (CHCR priorities),
select the view either in the canvas or in the document outline. Open the Size inspector,
and scroll down until you find the Content Hugging Priority and Compression Resistance
Priority settings.
You can also set the view’s intrinsic size in Interface Builder. By default, Interface Builder
uses the size returned from the view’s intrinsicContentSize method. However, if you
need a different size at design time, you can set a placeholder intrinsic content size. This
placeholder affects the size of the view only in Interface Builder. It does not have any
effect on the view at runtime.

For more information, see Setting the Placeholder Intrinsic Size for a Custom View in Auto
Layout Help.

iOS-Only Features
iOS adds a few unique features that interact with Auto Layout. These include the top and
bottom layout guides, a view’s layout margins, a view’s readable content guides, and a
view’s semantic content.

Top and Bottom Layout Guides


The top and bottom layout guides represent the upper and lower edge of the visible
content area for the currently active view controller. If you don’t want your content to
extend under transparent or translucent UIKit bars (for example, a status bar, navigation
bar, or tab bar), use Auto Layout to pin your content to the respective layout guide.

The layout guides adopt the UILayoutSupport protocol, giving the guide a length
property, which measures the distance between the guide and the respective edge of the
view. Specifically:

• For the top layout guide, length indicates the distance, in points, between the top of
a view controller’s view and the bottom of the bottommost bar that overlays the view.
• For the bottom layout guide, length indicates the distance, in points, between the
bottom of a view controller’s view and the top the bar (such as a tab bar) that
overlays the view.

These guides can also act as items in a constraint, supporting the top, bottom, and height
attributes. Typically, you constrain views to the top layout guide’s bottom attribute or to the
bottom layout guide’s top attribute. The guides also provide topAnchor, bottomAnchor, and
heightAnchor properties, to simplify the programmatic creation of constraints.

Interface Builder automatically offers the top and bottom layout guides as options when
creating constraints to the root view’s top or bottom edge as appropriate. If the layout
guide is the view’s nearest neighbor, Interface Builder uses the guide by default. When
using the Pin tool you can switch between the layout guide and the root view’s edge, as
needed. Just click on the disclosure triangle.

Layout Margins
Auto Layout defines margins for each view. These margins describe the preferred spacing
between the edge of the view and its subviews. You can access the view’s margins using
either the layoutMargins or layoutMarginsGuide property. The layoutMargins property
lets you get and set the margins as a UIEdgeInsets structure. The layoutMarginsGuide
property provides read-only access to the margins as a UILayoutGuide object.
Additionally, use the preservesSuperviewLayoutMargins property to determine how the
view’s margins interact with its superview’s margins.

The default margins are 8 points on each side. You can modify these margins based on
your app’s needs.

NOTE

The system sets and manages the margins of a view controller’s root view. The top and
bottom margins are set to zero points, making it easy to extend content under the bars (if
any). The side margins vary depending on how and where the controller is presented, but
can be either 16 or 20 points. You cannot change these margins.

When constraining a view to its superview, you typically use the layout margins instead of
the view’s edge. In UIKit, the NSLayoutAttribute enumeration defines a number of
attributes to represent top, bottom, leading, trailing, left, and right margins. It also includes
attributes for the center X and center Y relative to the margins.

In Interface Builder, Control-dragging a constraint between a view and its superview uses
the margin attributes by default. When using the Pin tool, you can toggle the “Constrain to
margins” checkbox. If it’s checked, the resulting constraints use the superview’s margin
attributes. If it’s unchecked, they use the superview’s edges. Similarly, when editing a
constraint in the Attribute inspector, the First Item and Second Item’s pop-down menus
include a “Relative to margin” option. Select this item to use the margin attribute. Deselect
it to use the edge.

Finally, when programmatically creating constraints to the superview’s margins, use the
layoutMarginsGuide property and create constraints to the layout guide directly. This lets
you use the guide’s layout anchors to create your constraints, providing a streamlined API
that is easier to read.

Readable Content Guides


The view’s readableContentGuide property contains a layout guide that defines the
maximum optimal width for text objects inside the view. Ideally, the content is narrow
enough that users can read it without having to move their head.

This guide is always centered inside the view’s layout margin and never extends beyond
those margins. The size of the guide also varies depending on the size of the system’s
dynamic type. The system creates wider guides when the user selects larger fonts,
because users typically hold the device farther from them while reading.

In Interface Builder, you can set whether the view’s margins represent the layout margins
or the readable content guide. Select the view (typically the view controller’s root view),
and open the Size inspector. If you select the Follow Readable Width checkbox, any
constraints drawn to the view’s margins use the readable content guide instead.
NOTE

For most devices there is little or no difference between the readable content guides and
the layout margins. The difference becomes obvious only when working on an iPad in
landscape orientation.

Semantic Content
If you lay out your views using leading and trailing constraints, the views automatically flip
positions when switching between left-to-right languages (like English) and right-to-left
languages (like Arabic). However, some interface elements should not change their
position based on the reading direction. For example, buttons that are based on physical
directions (up, down, left, and right) should always stay in the same relative orientation.

The view’s semanticContentAttribute property determines whether the view’s content


should flip when switching between left-to-right and right-to-left languages.

In Interface Builder, set the Semantic option in the Attribute inspector. If the value is
Unspecified, the view’s content flips with the reading direction. If it is set to Spatial,
Playback, or Force Left-to-Right, the content is always laid out with the leading edges to
the left and trailing edges to the right. Force Right-to-Left always lays out the content with
the leading edges to the right and the trailing edges to the left.

Rules of Thumb
The following guidelines will help you succeed with Auto Layout. There are undoubtedly a
number of legitimate exceptions for each of these rules. However, if you decide to veer
from them, pause and carefully consider your approach before proceeding.

• Never specify a view’s geometry using its frame, bounds, or center properties.
• Use stack views wherever possible
Stack views manage the layout of their content, greatly simplifying the constraint
logic needed for the rest of the layout. Resort to custom constraints only when a
stack view doesn’t provide the behavior you need.
• Create constraints between a view and its nearest neighbor.
If you have two buttons next to each other, constrain the leading edge of the second
button to the trailing edge of the first. The second button generally should not have a
constraint that reaches across the first button to the view’s edge.
• Avoid giving views a fixed height or width.
The whole point of Auto Layout is to dynamically respond to changes. Setting a fixed
size removes the view’s ability to adapt. However, you may want to set a minimum
or maximum size for the view.
• If you are having trouble setting constraints, try using the Pin and Align tools.
Although these tools can be somewhat slower than Control-dragging, they do let you
verify the exact values and items involved before creating the constraint. This extra
sanity check can be helpful, especially when you are first starting out.
• Be careful when automatically updating an item’s frame. If the item does not have
enough constraints to fully specify its size and position, the update’s behavior is
undefined. Views often disappear either because their height or width gets set to
zero or because they are accidentally positioned off screen.
You can always try to update an item’s frame, and then undo the change, if
necessary.

• Make sure all the views in your layout have meaningful names. This makes it much
easier to identify your views when using the tools.
The system automatically names labels and buttons based on their text or title. For
other views, you may need to set an Xcode specific label in the Identity inspector (or
by double-clicking and editing the view’s name in the document outline).

• Always use leading and trailing constraints instead of right and left.
You can always adjust how the view interprets its leading and trailing edges using its
semanticContentAttribute property (iOS) or its userInterfaceLayoutDirection
property (OS X).
• In iOS, when constraining an item to the edge of the view controller’s root view, use
the following constraints:

• Horizontal constraints. For most controls, use a zero-point constraint to the


layout margins. The system automatically provides the correct spacing based
on what the device is and how the app presents the view controller.
For text objects that fill the root view from margin to margin, use the readable
content guides instead of the layout margins.
For items that need to fill the root view from edge to edge (for example,
background images), use the view’s leading and trailing edges.
• Vertical constraints. If the view extends under the bars, use the top and
bottom margins. This is particularly common for scroll views, allowing the
content to scroll under the bars. Note, however, that you may need to modify
the scroll view’s contentInset and scrollIndicatorInsets properties to
correctly set the content’s initial position.
If the view does not extend under the bars, constrain the view to the top and
bottom layout guides instead.

• When programmatically instantiating views, be sure to set their


translatesAutoresizingMaskIntoConstraints property to NO. By default, the
system automatically creates a set of constraints based on the view’s frame and its
autoresizing mask. When you add your own constraints, they inevitably conflict with
the autogenerated constraints. This creates an unsatisfiable layout.
• Be aware that OS X and iOS calculate their layouts differently.
In OS X, Auto Layout can modify both the contents of a window and the window’s
size.
In iOS, the system provides the size and layout of the scene. Auto Layout can
modify only the contents of the scene.
These differences seem relatively minor, but they can have a profound impact on
how you design your layout, especially on how you use priorities.
Stack Views
The following recipes show how you can use stack views to create layouts of increasing
complexity. Stack views are a powerful tool for quickly and easily designing your user
interfaces. Their attributes allow a high degree of control over how they lay out their
arranged views. You can augment these settings with additional, custom constraints;
however, this increases the layout’s complexity.

To view the source code for these recipes, see the Auto Layout Cookbook project.

Simple Stack View


This recipe uses a single, vertical stack view to lay out a label, image view, and button.
Views and Constraints
In Interface Builder, start by dragging out a vertical stack view, and add the flowers label,
image view, and edit button. Then set up the constraints as shown.

1. Stack View.Leading = Superview.LeadingMargin


2. Stack View.Trailing = Superview.TrailingMargin
3. Stack View.Top = Top Layout Guide.Bottom + Standard
4. Bottom Layout Guide.Top = Stack View.Bottom + Standard

Attributes
In the Attributes inspector, set the following stack view attributes:

Stack Axis Alignment Distribution Spacing

Stack View Vertical Fill Fill 8

Next, set the following attributes on the Image View:

View Attribute Value

Image View Image (an image of flowers)

Image View Mode Aspect Fit

Finally, in the Size inspector, set the Image View’s content-hugging and compression-
resistance (CHCR) priorities.
Name Horizontal Vertical Horizontal Vertical
hugging hugging resistance resistance

Image
250 249 750 749
View

Discussion
You must pin the stack view to the superview, but otherwise, the stack view manages the
entire layout without any other explicit constraints.

In this recipe, the stack view fills its superview, with a small, standard margin. The
arranged views are resized to fill the stack view’s bounds. Horizontally, each view is
stretched to match the stack view’s width. Vertically, the views are stretched based on
their CHCR priorities. The image view should always shrink and grow to fill the available
space. Therefore, its vertical content hugging and compression resistance priorities must
be lower than the label and button’s default priorities.

Finally, set the image view’s mode to Aspect Fit. This setting forces the image view to
resize the image so that it fits within the image view’s bounds, while maintaining the
image’s aspect ratio. This lets the stack view arbitrarily resize the image view without
distorting the image.

For more information on pinning a view to fill its superview, see Attributes and Adaptive
Single View.
Nested Stack Views
This recipe shows a complex layout built from multiple layers of nested stack views.
However, in this example, the stack views cannot create the wanted behaviors alone.
Instead, additional constraints are needed to further refine the layout.

After the view hierarchy is built, add the constraints shown in the next section, Views and
Constraints.

Views and Constraints


When working with nested stack views, it is easiest to work from the inside out. Begin by
laying out the name rows in Interface Builder. Position the label and text field in their
correct relative positions, select them both, and then click the Editor > Embed In > Stack
View menu item. This creates a horizontal stack view for the row.

Next, position these rows horizontally, select them, and click the Editor > Embed In >
Stack View menu item again. This creates a horizontal stack of rows. Continue to build the
interface as shown.
1. Root Stack View.Leading = Superview.LeadingMargin
2. Root Stack View.Trailing = Superview.TrailingMargin
3. Root Stack View.Top = Top Layout Guide.Bottom + 20.0
4. Bottom Layout Guide.Top = Root Stack View.Bottom + 20.0
5. Image View.Height = Image View.Width
6. First Name Text Field.Width = Middle Name Text Field.Width
7. First Name Text Field.Width = Last Name Text Field.Width

Attributes
Each stack has its own set of attributes. These define how the stack lays out its contents.
In the Attribute inspector, set the following attributes:

Stack Axis Alignment Distribution Spacing

First Name Horizontal First Baseline Fill 8

Middle Name Horizontal First Baseline Fill 8

Last Name Horizontal First Baseline Fill 8

Name Rows Vertical Fill Fill 8

Upper Horizontal Fill Fill 8

Button Horizontal First Baseline Fill Equally 8

Root Vertical Fill Fill 8


Additionally, give the text view a light gray background color. This makes it easier to see
how the text view is resized when the orientation changes.

View Attribute Value

Text View Background Light Gray Color

Finally, the CHCR priorities define which views should stretch to fill the available space. In
the Size inspector, set the following CHCR priorities:

Name Horizontal Vertical Horizontal Vertical


hugging hugging resistance resistance

Image View 250 250 48 48

Text View 250 249 250 250

First, Middle, and Last


251 251 750 750
Name Labels

First, Middle, and Last


48 250 749 750
Name Text Fields

Discussion
In this recipe, the stack views work together to manage most of the layout. However, they
cannot—by themselves—create all of the wanted behaviors. For example, the image
should maintain its aspect ratio as the image view is resized. Unfortunately, the technique
used in Simple Stack View won’t work here. The layout needs to fit close to both the
trailing and bottom edge of the image, and using the Aspect Fit mode would add extra
white space to one of those dimensions. Fortunately, in this example, the image’s aspect
ratio is always square, so you can let the image completely fill the image view’s bounds,
and constrain the image view to a 1:1 aspect ratio.

NOTE

In Interface Builder, an aspect ratio constraint is simply a constraint between a view’s


height and its width. Interface Builder can also show the multiplier for constraints in a
number of ways. Typically, for aspect ratio constraints, it shows them as a ratio. So, a
View.Width = View.Height constraint may appear as a 1:1 aspect ratio.

Additionally, all the text fields should be the same width. Unfortunately, they are all in
separate stack views, so the stacks cannot manage this. Instead, you must explicitly add
equal width constraints.

Like the simple stack view, you must also modify some of the CHCR priorities. These
define how the views shrink and grow as the superclass’s bounds change.

Vertically, you want the text view to expand to fill the space between the upper stack and
the button stack. Therefore, the text view’s vertical content hugging must be lower than
any other vertical content hugging priority.

Horizontally, the labels should appear at their intrinsic content size, while the text fields
resize to fill any extra space. The default CHCR priorities work well for the labels.
Interface Builder already sets the content hugging at 251, making it higher than the text
fields; however, you still need to lower both the horizontal content hugging and the
horizontal compression resistance of the text fields.

The image view should shrink so that it is the same height as the stack containing the
name rows. However, stack views only loosely hug their content. This means that the
image view’s vertical compression resistance must be very low, so the image view shrinks
instead of having the stack view expand. Additionally, the image view’s aspect ratio
constraint complicates the layout, because it allows the vertical and horizontal constraints
to interact. This means that the text fields’ horizontal content hugging must also be very
low, or they will prevent the image view from shrinking. In both cases, set the priority to a
value of 48 or lower.

Dynamic Stack View


This recipe demonstrates dynamically adding and removing items from a stack at runtime.
All changes to the stack are animated. Additionally, the stack view is placed inside a scroll
view, letting you scroll through the list if it is too long to fit on the screen.

NOTE

This recipe is only intended to demonstrate working dynamically with stack views, and
working with stack views inside scroll views. In a real-world app, this recipe’s behaviors
should be implemented using the UITableView class instead. In general, you should not
use dynamic stack views to simply implement a scratch-built table view clone. Instead, use
them to create dynamic user interfaces that you cannot easily build using any other
technology.
Views and Constraints
The initial user interface is quite simple. Place a scroll view on your scene, and size it so
that it fills the scene. Then, place a stack view inside the scroll view, and place the add
item button inside the stack view. As soon as everything’s in place, set the following
constraints:

1. Scroll View.Leading = Superview.LeadingMargin


2. Scroll View.Trailing = Superview.TrailingMargin
3. Scroll View.Top = Superview.TopMargin
4. Bottom Layout Guide.Top = Scroll View.Bottom + 20.0
5. Stack View.Leading = Scroll View.Leading
6. Stack View.Trailing = Scroll View.Trailing
7. Stack View.Top = Scroll View.Top
8. Stack View.Bottom = Scroll View.Bottom
9. Stack View.Width = Scroll View.Width

Attributes
In the Attributes inspector, set the following stack view attributes:

Stack Axis Alignment Distribution Spacing

Stack View Vertical Fill Equal Spacing 0


Code
This recipe requires a bit of code to add items to and remove them from the stack view.
Create a custom view controller for your scene with outlets for both the scroll view and
stack view.

1 class DynamicStackViewController: UIViewController {


2
3 @IBOutlet weak private var scrollView: UIScrollView!
4 @IBOutlet weak private var stackView: UIStackView!
5
6 // Method implementations will go here...
7
8 }

Next, override the viewDidLoad method to set the scroll view’s initial position. You want
the scroll view’s content to start below the status bar.

1 override func viewDidLoad() {


2 super.viewDidLoad()
3
4 // setup scrollview
5 let insets = UIEdgeInsetsMake(20.0, 0.0, 0.0, 0.0)
6 scrollView.contentInset = insets
7 scrollView.scrollIndicatorInsets = insets
8
9 }

Now, add an action method for the add item button.

1 // MARK: Action Methods


2
3 @IBAction func addEntry(sender: AnyObject) {
4
5 let stack = stackView
6 let index = stack.arrangedSubviews.count - 1
7 let addView = stack.arrangedSubviews[index]
8
9 let scroll = scrollView
10 let offset = CGPoint(x: scroll.contentOffset.x,
11 y: scroll.contentOffset.y +
addView.frame.size.height)
12
13 let newView = createEntry()
14 newView.hidden = true
15 stack.insertArrangedSubview(newView, atIndex: index)
16
17 UIView.animateWithDuration(0.25) { () -> Void in
18 newView.hidden = false
19 scroll.contentOffset = offset
20 }
21 }

This method calculates a new offset for the scroll view, then creates a new entry view. The
entry view is hidden, and added to the stack. Hidden views do not affect the appearance
or layout of a stack—so the stack’s appearance remains unchanged. Then, in an
animation block, the view is revealed and the scroll offset is updated, animating the view’s
appearance.

Add a similar method to delete entries; however, unlike the addEntry method, this method
is not linked to any controls in Interface Builder. Instead, the app will programmatically link
each entry view to this method when the view is created.

1 func deleteStackView(sender: UIButton) {


2 if let view = sender.superview {
3 UIView.animateWithDuration(0.25, animations: { () -> Void
in
4 view.hidden = true
5 }, completion: { (success) -> Void in
6 view.removeFromSuperview()
7 })
8 }
9 }

This method hides the view in an animation block. After the animation completes, it
removes the view from the view hierarchy. This automatically removes the view from the
stack’s list of arranged views.

Although the entry view could be any view, this example uses a stack view that contains a
date label, a label containing a random hex string, and a delete button.

1 // MARK: - Private Methods


2 private func createEntry() -> UIView {
3 let date = NSDateFormatter.localizedStringFromDate(NSDate(),
dateStyle: .ShortStyle, timeStyle: .NoStyle)
4 let number = "\(randomHexQuad())-\(randomHexQuad())-\
(randomHexQuad())-\(randomHexQuad())"
5
6 let stack = UIStackView()
7 stack.axis = .Horizontal
8 stack.alignment = .FirstBaseline
9 stack.distribution = .Fill
10 stack.spacing = 8
11
12 let dateLabel = UILabel()
13 dateLabel.text = date
14 dateLabel.font =
UIFont.preferredFontForTextStyle(UIFontTextStyleBody)
15
16 let numberLabel = UILabel()
17 numberLabel.text = number
18 numberLabel.font =
UIFont.preferredFontForTextStyle(UIFontTextStyleHeadline)
19
20 let deleteButton = UIButton(type: .RoundedRect)
21 deleteButton.setTitle("Delete", forState: .Normal)
22 deleteButton.addTarget(self, action: "deleteStackView:",
forControlEvents: .TouchUpInside)
23
24 stack.addArrangedSubview(dateLabel)
25 stack.addArrangedSubview(numberLabel)
26 stack.addArrangedSubview(deleteButton)
27
28 return stack
29 }
30
31 private func randomHexQuad() -> String {
32 return NSString(format: "%X%X%X%X",
33 arc4random() % 16,
34 arc4random() % 16,
35 arc4random() % 16,
36 arc4random() % 16
37 ) as String
38 }
39 }

Discussion
As this recipe demonstrates, views can be added or removed from stack views during
runtime. The stack’s layout automatically adjusts to compensate for changes to its array of
arranged views. There are, however, a couple of important points worth remembering:

• Hidden views are still inside stack’s array of arranged views. However, they are not
displayed and do not affect the layout of the other arranged views.
• Adding a view to the stack’s array of arranged views automatically adds it to the
view hierarchy.

• Removing a view from the stack’s array of arranged views does not automatically
remove it from the view hierarchy; however, removing the view from the view
hierarchy does removes it from the arranged views array.
• In iOS, the view’s hidden property is normally not animatable. However, this
property becomes animatable for views as soon as they are placed in a stack’s
arranged views array. The actual animation is managed by the stack, not the view.
Use the hidden property to animate adding views to or removing them from the
stack.

This recipe also introduces the idea of using Auto Layout with scroll views. Here, the
constraints between the stack and the scroll view set the size of the scroll view’s content
area. An equal width constraint explicitly sets the stack (and thus the content size) to fill
the scroll view horizontally. Vertically, the content size is based on the stack’s fitting size.
The stack view grows longer as the user adds more entries. Scrolling is automatically
enabled as soon as there is too much content to fit on the screen.

For more information, see Working with Scroll Views.


Simple Constraints
The following recipes demonstrate using relatively simple sets of constraints to create
common behaviors. Use these examples as the fundamental building blocks to create
larger, more complex layouts.

To view the source code for these recipes, see the Auto Layout Cookbook project.

Simple Single View


This recipe positions a single red view so that it fills its superview with a fixed margin
around all four edges.

Views and Constraints


In Interface Builder, drag a view out onto your scene, and resize it so that it fills the scene.
Use Interface Builder’s guidelines to select the correct position relative to the edge of the
superview.

NOTE

You do not need to worry about getting the view in the pixel perfect position. After you set
the constraints, the system will calculate its correct size and position.

As soon as the view is in place, set the following constraints:.


1. Red View.Leading = Superview.LeadingMargin
2. Red View.Trailing = Superview.TrailingMargin
3. Red View.Top = Top Layout Guide.Bottom + 20.0
4. Bottom Layout Guide.Top = Red View.Bottom + 20.0

Attributes
To give the view a red background color, set the following attributes in the Attributes
inspector:

View Attribute Value

Red View Background Red

Discussion
The constraints in this recipe keep the red view a fixed distance from the edge of the
superview. For the leading and trailing edges, pin your view to the superview’s margin. For
the top and bottom, pin your view to the top and bottom layout guide instead.

NOTE

The system automatically sets the root view’s margins so that it has an appropriate leading
and trailing margin (16- or 20-points, depending on the device), and a 0-point top and
bottom margin. This lets you easily flow content under any control bars (status bar,
navigation bar, tab bar, tool bar, etc.).
However, this recipe needs to place the content below the bars (if any). You can simply pin
the red view’s leading and trailing edges to the superview’s leading and trailing margins;
however you must set your own top and bottom margin relative to the layout guides.

By default, Interface Builder’s standard spacing is 20.0 points between a view and the
edge of its superview, and 8.0 points between sibling views. This implies that you should
use an 8.0-point space between the top of the red view and the bottom of the status bar.
However, the status bar disappears when the iPhone is in a landscape orientation, and
without the status bar, an 8.0-point space looks far too narrow.

Always select the layout that works best for your app. This recipe uses a fixed 20-point
margin for both the top and bottom. This keeps the constraint logic as simple as possible,
and still looks reasonable in all orientations. Other layouts may work better with a fixed 8-
point margin.

If you want a layout that adapts automatically to the presence or absence of bars, see
Adaptive Single View.

Adaptive Single View


This recipe positions a single, blue view so that it fills its superview with a margin around
all four edges. However, unlike the margins in the Simple Single View recipe, the top
margin on this recipe adapts based on the view’s context. If there’s a status bar, the view
is placed the standard spacing (8.0 points) below the status bar. If there is no status bar,
the view is placed 20.0 points below the edge of the superview.

You can see this when looking at the Simple and Adaptive views side by side.
Views and Constraints
In Interface Builder, drag a view out onto your scene, and resize it so that it fills the scene,
with its edges aligned to the guidelines. Then set the constraints as shown.

1. Blue View.Leading = Superview.LeadingMargin


2. Blue View.Trailing = Superview.TrailingMargin
3. Blue View.Top = Top Layout Guide.Bottom + Standard (Priority 750)
4. Blue View.Top >= Superview.Top + 20.0
5. Bottom Layout Guide.Top = Blue View.Bottom + Standard (Priority 750)
6. Superview.Bottom >= Blue View.Bottom + 20.0
Attributes
To give the view a blue background color, set the following attributes in the Attribute
inspector:

View Attribute Value

Blue View Background Blue

Discussion
This recipe creates adaptive margins for both the top and bottom of the blue view. If
there’s a bar, the view’s edge is placed 8 points away from the bar. If there is no bar, the
edge is positioned 20 points away from the edge of the superview.

This recipe uses the layout guides to correctly position its contents. The system sets the
position of these guides based on the presence and size of any bars. The top layout guide
is positioned along the bottom edge of any top bars (for example, status bars and
navigation bars). The bottom layout guide is positioned along the top edge of any bottom
bars (for example, tab bars). If there isn’t a bar, the system positions the layout guide
along the superview’s corresponding edge.

The recipe uses a pair of constraints to build the adaptive behavior. The first constraint is
a required, greater-than-or-equal constraint. This constraint guarantees that the blue
view’s edge is always at least 20-points away from the superview’s edge. In effect, it
defines a minimum, 20-point margin.

Next, an optional constraint tries to position the view 8-points away from the
corresponding layout guide. Because this constraint is optional, if the system cannot
satisfy the constraint, it will still attempt to come as close as possible, and the constraint
acts like a spring-like force, pulling the edge of the blue view towards its layout guide.

If the system is not displaying a bar, then the layout guide is equal to the superview’s
edge. The blue view’s edge cannot be both 8 points and 20 points (or more) from the
superview’s edge. Therefore, the system cannot satisfy the optional constraint. Still, it tries
to get as close as it can—setting the margin to the 20-point minimum.

If a bar is present, then both constraints can be satisfied. All the bars are at least 20 points
wide. So, if the system places the edge of the blue view 8 points away from the edge of
the bar, it is guaranteed to be more than 20 points from the edge of the superview.

This technique, using a pair of constraints that act as forces pushing in opposite
directions, is commonly used to create adaptive layouts. You will see it again, when we
look at the content-hugging and compression-resistance (CHCR) priorities in Views with
Intrinsic Content Size.
Two Equal-Width Views
This recipe lays out two views, side by side. The views always have the same width,
regardless of how the superview’s bounds change. Together, they fill the superview, with a
fixed margin on all sides, and a standard-spaced margin between them.

Views and Constraints


In Interface Builder, drag out two views and position them so they fill the scene, using the
guidelines to set the correct spacing between the objects in the scene.

Don’t worry about making the views the same width. Just get the rough, relative position,
and let the constraints do the hard work.

As soon as the views are in place, set the constraints as shown.


1. Yellow View.Leading = Superview.LeadingMargin
2. Green View.Leading = Yellow View.Trailing + Standard
3. Green View.Trailing = Superview.TrailingMargin
4. Yellow View.Top = Top Layout Guide.Bottom + 20.0
5. Green View.Top = Top Layout Guide.Bottom + 20.0
6. Bottom Layout Guide.Top = Yellow View.Bottom + 20.0
7. Bottom Layout Guide.Top = Green View.Bottom + 20.0
8. Yellow View.Width = Green View.Width

Attributes
Set the views’ background colors in the Attributes inspector.

View Attribute Value

Yellow View Background Yellow

Green View Background Green

Discussion
This layout explicitly defines the top and bottom margins for both views. As long as these
margins are the same, the views will implicitly be the same height. However, this is not the
only possible solution to this layout. Instead of pinning the green view’s top and bottom to
the superview, you could set them equal to the yellow view’s top and bottom. Aligning the
top and bottom edges explicitly gives the views the same vertical layout.

Even a relatively simple layout like this can be created using a number of different
constraints. Some are clearly better than others, but many of them may be roughly
equivalent. Each approach has its own set of advantages and disadvantages. This
recipe’s approach has two main advantages. First (and most importantly), it is easy to
understand. Second, the layout would remain mostly intact if you removed one of the
views.

Removing a view from the view hierarchy also removes all the constraints for that view.
This means, if you removed the yellow view, constraints 1, 2, 4, 6 and 8 would all be
removed. However, that still leaves three constraints holding the green view in place. You
simply need to add one more constraint to define the position of the green view’s leading
edge, and the layout is fixed.

The main disadvantage is the fact that you need to manually ensure that all the top
constraints and bottom constraints are equal. Change the constant on one of them, and
the views become obviously uneven. In practice, setting consistent constants is relatively
easy when you use Interface Builder’s Pin tool to create your constraints. If you use drag
and drop to create the constraints, it can become somewhat more difficult.

When faced with multiple, equally valid sets of constraints, pick the set that is easiest to
understand and easiest to maintain within the context of your layout. For example, if
you’re center aligning a number of different sized views, it’s probably easiest to constrain
the views’ Center X attribute. For other layouts, it may be easier to reason about the
view’s edges, or their heights and widths.

For more information on selecting the best set of constraints for your layout, see Creating
Nonambiguous, Satisfiable Layouts.

Two Different-Width Views


This recipe is very similar to the Two Equal-Width Views recipe, with one significant
difference. In this recipe, the orange view is always twice as wide as the purple view.

Views and Constraints


As before, drag out two views and position them so they are roughly in the correct place.
Then, set the constraints as shown.
1. Purple View.Leading = Superview.LeadingMargin
2. Orange View.Leading = Purple View.Trailing + Standard
3. Orange View.Trailing = Superview.TrailingMargin
4. Purple View.Top = Top Layout Guide.Bottom + 20.0
5. Orange View.Top = Top Layout Guide.Bottom + 20.0
6. Bottom Layout Guide.Top = Purple View.Bottom + 20.0
7. Bottom Layout Guide.Top = Orange View.Bottom + 20.0
8. Orange View.Width = 2.0 x Purple View.Width

Attributes
Set the views’ background colors in the Attributes inspector.

View Attribute Value

Purple View Background Purple

Orange View Background Orange

Discussion
This recipe uses a multiplier on the width constraint. Multipliers can only be used on
constraints to a view’s height or width. It lets you set the relative size of two different
views. Alternatively, you can set a constraint between the view’s own height and width,
specifying the view’s aspect ratio.

Interface Builder lets you specify the multiplier using a number of different formats. You
can write the multiplier as a decimal number (2.0), a percentage (200%), a fraction (2/1),
or a ratio (2:1).
Two Views with Complex Widths
This recipe is almost identical to the one in Two Different-Width Views; however, here you
use a pair of constraints to define a more complex behavior for the view widths. In this
recipe, the system tries to make the red view twice as wide as the blue view, but the blue
view has a 150-point minimum width. So, on iPhone in portrait the views are almost the
same width, and in landscape both views are larger, but the red view is now twice as wide
as the blue.

Views and Constraints


Position the views on the canvas, and then set the constraints as shown.

1. Blue View.Leading = Superview.LeadingMargin


2. Red View.Leading = Blue View.Trailing + Standard
3. Red View.Trailing = Superview.TrailingMargin
4. Blue View.Top = Top Layout Guide.Bottom + 20.0
5. Red View.Top = Top Layout Guide.Bottom + 20.0
6. Bottom Layout Guide.Top = Blue View.Bottom + 20.0
7. Bottom Layout Guide.Top = Red View.Bottom + 20.0
8. Red View.Width = 2.0 x Blue View.Width (Priority 750)
9. Blue View.Width >= 150.0

Attributes
Set the views’ background colors in the Attributes inspector.

View Attribute Value

Blue View Background Blue

Red View Background Red

Discussion
This recipe uses a pair of constraints to control the views’ widths. The optional,
proportional width constraint pulls the views so that the red view is twice as wide as the
blue view. However, the required greater-than-or-equal constraint defines a constant
minimum width for the blue view.

In effect, if the distance between the superview’s leading and trailing margin is 458.0
points or greater (150.0 + 300.0 + 8.0), then the red view is twice as big as the blue view.
If the distance between the margins is smaller, then the blue view is set to 150.0 points
wide, and the red view fills the remaining space (with an 8.0-point margin between the
views).

You might recognize this as yet another variation on the pattern introduced in the Adaptive
Single View recipe.

You can extend this design by adding additional constraints—for example, by using three
constraints. A required constraint to set the red view’s minimum width. A high-priority
optional constraint to set the blue view’s minimum width, and a lower priority optional
constraint to set the preferred size ratio between the views.
Views with Intrinsic Content Size
The following recipes demonstrate working with views that have an intrinsic content size.
In general, the intrinsic content size simplifies the layout, reducing the number of
constraints you need. However, using the intrinsic content size often requires setting the
view’s content-hugging and compression-resistance (CHCR) priorities, which can add
additional complications.

To view the source code for these recipes, see the Auto Layout Cookbook project.

Simple Label and Text Field


This recipe demonstrates laying out a simple label and text field pair. In this example, the
label’s width is based on the size of its text property, and the text field expands and
shrinks to fit the remaining space.

Because this recipe uses the view’s intrinsic content size, you need only five constraints to
uniquely specify the layout. However, you must make sure you have the correct CHCR
priorities to get the correct resizing behavior.

For more information on intrinsic content sizes and CHCR priorities, see Intrinsic Content
Size.

Views and Constraints


In Interface Builder, drag out a label and a text field. Set the label’s text and the text field’s
placeholder, and then set up the constraints as shown.
1. Name Label.Leading = Superview.LeadingMargin
2. Name Text Field.Trailing = Superview.TrailingMargin
3. Name Text Field.Leading = Name Label.Trailing + Standard
4. Name Text Field.Top = Top Layout Guide.Bottom + 20.0
5. Name label.Baseline = Name Text Field.Baseline

Attributes
To have the text field stretch to fill the available space, its content hugging must be lower
than the label’s. By default, Interface Builder should set the label’s content hugging to 251,
and the text field to 250. You can verify this in the Size inspector.

Name Horizontal Vertical Horizontal Vertical


hugging hugging resistance resistance

Name Label 251 251 750 750

Name Text
250 250 750 750
Field

Discussion
Notice that this layout only uses two constraints (4 and 5) to define the vertical layout, and
three constraints (1, 2, and 3) to define the horizontal layout. The rule of thumb from
Creating Nonambiguous, Satisfiable Layouts states that we need two horizontal and two
vertical constraints per view; however, the label and text field’s intrinsic content size
provides their heights and the label’s widths, removing the need for three constraints.

This layout also makes the simplifying assumption that the text field is always taller than
the label text, and it uses the text field’s height to define the distance from the top layout
guide. Because both the label and text field are used to display text, the recipe aligns
them using the text’s baseline.

Horizontally, you still need to define which view should expand to fill the available size.
You do this by modifying the view’s CHCR priorities. In this example, Interface Builder
should already set the name label’s horizontal and vertical hugging priority to 251.
Because this is larger than the text field’s default 250, the text field expands to fill any
additional space.
NOTE

If the layout might be displayed in a space that is too small for the controls, you need to
modify the compression resistances values as well. The compression resistance defines
which of the views should be truncated when there isn’t enough space.
In this example, modifying the compression resistances is left as an exercise for the
reader. If the name label’s text or font is large enough; however, there won’t be enough
space, producing an ambiguous layout. The system then selects a constraint to break, and
either the text field or the label is truncated.
Ideally, you want to create a layout that is never too big for the available space—using
alternative layouts for compact size classes as necessary. However, when designing for
views that support multiple languages and dynamic type, it is difficult to predict exactly
how big your rows might become. Modifying the compression resistance is a good safety
valve, just in case.

Dynamic Height Label and Text Field


The Simple Label and Text Field recipe simplified the layout logic by assuming that the
text field would always be taller than the name label. That, however, is not necessarily
always true. If you increase the label’s font size enough, it will extend above the text field.

This recipe dynamically sets the vertical spacing of the controls based on the tallest
control at runtime. With the regular system font, this recipe appears to be identical to the
Simple Label and Text Field recipe (see the screenshot). However, if you increase the
label’s font size to 36.0 points, then the layout’s vertical spacing is calculated from the top
of the label instead.

This is a somewhat contrived example. After all, if you increase the font size of a label,
you would typically also increase the font size of the text field. However, given the extra,
extra, extra large fonts available through the iPhone’s accessibility settings, this technique
can prove useful when mixing dynamic type and fixed-sized controls (like images).
Views and Constraints
Set up the view hierarchy as you did in Simple Label and Text Field, but use a somewhat
more complex set of constraints:

1. Name Label.Leading = Superview.LeadingMargin


2. Name Text Field.Trailing = Superview.TrailingMargin
3. Name Text Field.Leading = Name Label.Trailing + Standard
4. Name Label.Top >= Top Layout Guide.Bottom + 20.0
5. Name Label.Top = Top Layout Guide.Bottom + 20.0 (Priority 249)
6. Name Text Field.Top >= Top Layout Guide.Bottom + 20.0
7. Name Text Field.Top = Top Layout Guide.Bottom + 20.0 (Priority 249)
8. Name label.Baseline = Name Text Field.Baseline

Attributes
To have the text field stretch to fill the available space, it’s content hugging must be lower
than the label’s. By default, Interface Builder should set the label’s content hugging to 251,
and the text field to 250. You can verify this in the Size inspector.

Name Horizontal Vertical Horizontal Vertical


hugging hugging resistance resistance

Name Label 251 251 750 750

Name Text
250 250 750 750
Field

Discussion
This recipe uses a pair of constraints for each control. A required, greater-than-or-equal
constraint defines the minimum distance between that control and the layout guide, while
an optional constraint tries to pull the control to exactly 20.0 points from the layout guide.

Both constraints are satisfiable for the taller constraint, so the system places it exactly
20.0 points from the layout guide. However, for the shorter control, only the minimum
distance is satisfiable. The other constraint is ignored. This lets the Auto Layout system
dynamically recalculate the layout as the height of the controls change at runtime.

NOTE

Be sure to set the priority of the optional constraints to a value that is lower than the
default content hugging constraint (250). Otherwise, the system breaks the content
hugging constraint and stretches the view instead of repositioning it.
This can be particularly confusing when working with layouts that use baseline alignments,
because the baseline alignments are only valid if the text views are displayed at their
intrinsic content height. If the system resizes one of the views, the text may not line up
properly, despite having a required baseline constraint.

Fixed Height Columns


This recipe extends the Simple Label and Text Field recipe into columns of labels and text
fields. Here, the trailing edge of all the labels are aligned. The text fields leading and
trailing edges are aligned, and the horizontal placement is based on the longest label. Like
the Simple Label and Text Field recipe, however, this recipe simplifies the layout logic by
assuming that the text fields are always taller than the labels.
Views and Constraints
Lay out the labels and text fields, and then set the constraints as shown.

1. First Name Label.Leading = Superview.LeadingMargin


2. Middle Name Label.Leading = Superview.LeadingMargin
3. Last Name Label.Leading = Superview.LeadingMargin
4. First Name Text Field.Leading = First Name Label.Trailing + Standard
5. Middle Name Text Field.Leading = Middle Name Label.Trailing + Standard
6. Last Name Text Field.Leading = Last Name Label.Trailing + Standard
7. First Name Text Field.Trailing = Superview.TrailingMargin
8. Middle Name Text Field.Trailing = Superview.TrailingMargin
9. Last Name Text Field.Trailing = Superview.TrailingMargin
10. First Name Label.Baseline = First Name Text Field.Baseline
11. Middle Name Label.Baseline = Middle Name Text Field.Baseline
12. Last Name Label.Baseline = Last Name Text Field.Baseline
13. First Name Text Field.Width = Middle Name Text Field.Width
14. First Name Text Field.Width = Last Name Text Field.Width
15. First Name Text Field.Top = Top Layout Guide.Bottom + 20.0
16. Middle Name Text Field.Top = First Name Text Field.Bottom + Standard
17. Last Name Text Field.Top = Middle Name Text Field.Bottom + Standard

Attributes
In the Attributes inspector, set the following attributes. In particular, right align the text in all
the labels. This lets you use labels that are longer than their text, and still line up the
edges beside the text fields.
View Attribute Value

First Name Label Text First Name

First Name Label Alignment Right

First Name Text Field Placeholder Enter first name

Middle Name Label Text Middle Name

Middle Name Label Alignment Right

Middle Name Text Field Placeholder Enter middle name

Last Name Label Text Last Name

Last Name Label Alignment Right

Last Name Text Field Placeholder Enter last name

For each pair, the label’s content hugging must be higher than the text fields. Again,
Interface Builder should do this automatically; however, you can verify these priorities in
the Size inspector.

Name Horizontal Vertical Horizontal Vertical


hugging hugging resistance resistance

First Name
251 251 750 750
Label

First Name Text


250 250 750 750
Field

Middle Name
251 251 750 750
Label

Middle Name
250 250 750 750
Text Field

Last Name
251 251 750 750
Label

Last Name Text


250 250 750 750
Field

Discussion
This recipe basically starts as three copies of the Simple Label and Text Field layout,
stacked one on top of the other. However, you need to make a few additions so that the
rows line up properly.

First, simplify the problem by right aligning the text for each of the labels. You can now
make all the labels the same width, and regardless of the length of the text, you can easily
align their trailing edges. Additionally, because a label’s compression resistance is greater
than its content hugging, all the labels prefer to be stretched rather than squeezed. Align
the leading and trailing edges, and the labels all naturally stretch to the intrinsic content
size of the longest label.

Therefore, you just need to align the leading and trailing edge of all the labels. You also
need to align the leading and trailing edges of all the text fields. Fortunately, the labels’
leading edges are already aligned with the superview’s leading margin. Similarly, the text
fields’ trailing edges are all aligned with the superview’s trailing margin. You just need to
line up one of the other two edges, and because all the rows are the same width,
everything will be aligned.

There are a number of ways to do this. For this recipe, give each of the text fields an
equal width.

Dynamic Height Columns


This recipe combines everything you learned in the Dynamic Height Label and Text Field
recipe and the Fixed Height Columns recipe. The goals of this recipe include:

• The trailing edge of the labels are aligned, based on the length of the longest label.
• The text fields are the same width, and their leading and trailing edges are aligned.
• The text fields expand to fill all the remaining space in the superview.
• The height between rows are based on the tallest element in the row.
• Everything is dynamic, so if the font size or label text changes, the layout
automatically updates.

Views and Constraints


Layout the labels and text fields as you did in Fixed Height Columns; however, you need a
few additional constraints.
1. First Name Label.Leading = Superview.LeadingMargin
2. Middle Name Label.Leading = Superview.LeadingMargin
3. Last Name Label.Leading = Superview.LeadingMargin
4. First Name Text Field.Leading = First Name Label.Trailing + Standard
5. Middle Name Text Field.Leading = Middle Name Label.Trailing + Standard
6. Last Name Text Field.Leading = Last Name Label.Trailing + Standard
7. First Name Text Field.Trailing = Superview.TrailingMargin
8. Middle Name Text Field.Trailing = Superview.TrailingMargin
9. Last Name Text Field.Trailing = Superview.TrailingMargin
10. First Name Label.Baseline = First Name Text Field.Baseline
11. Middle Name Label.Baseline = Middle Name Text Field.Baseline
12. Last Name Label.Baseline = Last Name Text Field.Baseline
13. First Name Text Field.Width = Middle Name Text Field.Width
14. First Name Text Field.Width = Last Name Text Field.Width
15. First Name Label.Top >= Top Layout Guide.Bottom + 20.0
16. First Name Label.Top = Top Layout Guide.Bottom + 20.0 (Priority 249)
17. First Name Text Field.Top >= Top Layout Guide.Bottom + 20.0
18. First Name Text Field.Top = Top Layout Guide.Bottom + 20.0 (Priority
249)

19. Middle Name Label.Top >= First Name Label.Bottom + Standard


20. Middle Name Label.Top = First Name Label.Bottom + Standard (Priority
249)

21. Middle Name Text Field.Top >= First Name Text Field.Bottom + Standard
22. Middle Name Text Field.Top = First Name Text Field.Bottom + Standard
(Priority 249)

23. Last Name Label.Top >= Middle Name Label.Bottom + Standard


24. Last Name Label.Top = Middle Name Label.Bottom + Standard (Priority 249)
25. Last Name Text Field.Top >= Middle Name Text Field.Bottom + Standard
26. Last Name Text Field.Top = Middle Name Text Field.Bottom + Standard
(Priority 249)

Attributes
In the Attributes inspector, set the following attributes. In particular, right align the text in all
the labels. Right aligning the labels lets you use labels that are longer than their text, and
the edge of the text still lines up beside the text fields.

View Attribute Value

First Name Label Text First Name

First Name Label Alignment Right

First Name Text Field Placeholder Enter first name

Middle Name Label Text Middle Name

Middle Name Label Alignment Right

Middle Name Text Field Placeholder Enter middle name

Last Name Label Text Last Name

Last Name Label Alignment Right

Last Name Text Field Placeholder Enter last name

For each pair, the label’s content hugging must be higher than the text fields. Again,
Interface Builder should do this automatically; however, you can verify these priorities in
the Size inspector.

Name Horizontal Vertical Horizontal Vertical


hugging hugging resistance resistance

First Name
251 251 750 750
Label

First Name Text


250 250 750 750
Field

Middle Name
251 251 750 750
Label

Middle Name
250 250 750 750
Text Field

Last Name
251 251 750 750
Label

Last Name Text


250 250 750 750
Field
Discussion
This recipe simply combines the techniques described in the Dynamic Height Label and
Text Field and Fixed Height Columns recipes. Like the Dynamic Height Label and Text
Field recipe, this recipe uses pairs of constraints to dynamically set the vertical spacing
between the rows. Like the Fixed Height Columns recipe, it uses right-aligned text in the
labels, and explicit equal width constraints to line up the columns.

NOTE

This example uses a 20.0-point space for the distance between views and the top layout
guide, and an 8.0-space between sibling views. This has the effect of setting a fixed, 20-
point top margin. If you want a margin that adjusts automatically to the presence or
absence of bars—you must add additional constraints. The general technique is shown in
the Adaptive Single View recipe. However, the exact implementation is left as a challenge
for the reader.

As you can see, the layout’s logic is beginning to grow somewhat complex; however, there
are a couple of ways you can simplify things. First, as mentioned earlier, you should use
stack views wherever possible. Alternatively, you can group controls, and then lay out the
groups. This lets you break up a single, complex layout into smaller, more manageable
chunks.

Two Equal-Width Buttons


This recipe demonstrates laying out two equal sized buttons. Vertically, the buttons are
aligned with the bottom of the screen. Horizontally, they are stretched so that they fill all
the available space.

Views and Constraints


In Interface Builder, drag two buttons onto the scene. Align them using the guidelines
along the bottom of the scene. Don’t worry about making the buttons the same width—just
stretch one of them to fill the remaining horizontal space. After they are roughly in place,
set the following constraints. Auto Layout will calculate their correct, final position.
1. Short Button.Leading = Superview.LeadingMargin
2. Long Button.Leading = Short Button.Trailing + Standard
3. Long Button.Trailing = Superview.TrailingMargin
4. Bottom Layout Guide.Top = Short Button.Bottom + 20.0
5. Bottom Layout Guide.Top = Long Button.Botton + 20.0
6. Short Button.Width = Long Button.Width

Attributes
Give the buttons a visible background color, to make it easier to see how their frames
change as the device rotates. Additionally, use different length titles for the buttons, to
show that the button title does not affect the button’s width.

View Attribute Value

Short Button Background Light Gray Color

Short Button Title short

Long Button Background Light Gray Color

Long Button Title Much Longer Button Title

Discussion
This recipe uses the buttons’ intrinsic height, but not their width when calculating the
layout. Horizontally, the buttons are explicitly sized so that they have an equal width and
fill the available space. To see how the button’s intrinsic height affects the layout, compare
this recipe with the Two Equal-Width Views recipe. In this recipe, there are only two
vertical constraints, not four.

The buttons are also given titles with very different lengths to help illustrate how the
button’s text affects (or in this case, does not affect) the layout.

NOTE

For this recipe, the buttons have been given a light gray background color, letting you see
their frames. Typically, buttons and labels have transparent backgrounds, making it difficult
(if not impossible) to see any changes to their frame.
Three Equal-Width Buttons
This recipe extends the Two Equal-Width Buttons recipe, so that it uses three equal-width
buttons.

Views and Constraints


Lay out the buttons and set the constraints as shown.

1. Short Button.Leading = Superview.LeadingMargin


2. Medium Button.Leading = Short Button.Trailing + Standard
3. Long Button.Leading = Medium Button.Trailing + Standard
4. Long Button.Trailing = Superview.TrailingMargin
5. Bottom Layout Guide.Top = Short Button.Bottom + 20.0
6. Bottom Layout Guide.Top = Medium Button.Bottom + 20.0
7. Bottom Layout Guide.Top = Long Button.Bottom + 20.0
8. Short Button.Width = Medium Button.Width
9. Short Button.Width = Long Button.Width

Attributes
Give the buttons a visible background color, to make it easier to see how their frames
change as the device rotates. Additionally, use different length titles for the buttons, to
show that the button title does not affect the button’s width.
Para View Attribute Value

Short Button Background Light Gray Color

Short Button Title Short

Medium Button Background Light Gray Color

Medium Button Title Medium

Long Button Background Light Gray Color

Long Button Title Long Button Title

Discussion
Adding an extra button requires adding three extra constraints (two horizontal constraints
and one vertical constraints). Remember, you are not using the button’s intrinsic width, so
you need at least two horizontal constraints to uniquely specify both its position and its
size. However, you are using the button’s intrinsic height, so you only need one additional
constraint to specify its vertical position.

NOTE

To quickly set the equal width constraints, select all three buttons, then use Interface
Builder’s Pin tool to create an equal width constraint. Interface Builder automatically
creates all both required constraints.

Two Buttons with Equal Spacing


Superficially, this recipe resembles the Two Equal-Width Buttons recipe (see Screenshot).
However, in this recipe, the buttons’ widths are based on the longest title. If there’s
enough space, the buttons are stretched only until they both match the intrinsic content
size of the longer button. Any additional space is divided evenly around the buttons.

On the iPhone, the Two Equal-Width Buttons and Two Buttons with Equal Spacing layouts
appear nearly identical in the portrait orientation. The difference becomes obvious only
when you rotate the device into a landscape orientation (or use a larger device, like an
iPad).

Views and Constraints


In Interface Builder, drag out and position two buttons and three view objects. Position the
buttons between the views, and then set the constraints as shown.

1. Leading Dummy View.Leading = Superview.LeadingMargin


2. Short Button.Leading = Leading Dummy View.Trailing
3. Center Dummy View.Leading = Short Button.Trailing
4. Long Button.Leading = Center Dummy View.Trailing
5. Trailing Dummy View.Leading = Long Button.Trailing
6. Trailing Dummy View.Trailing = Superview.TrailingMargin
7. Bottom Layout Guide.Top = Leading Dummy View.Bottom + 20.0
8. Bottom Layout Guide.Top = Short Button.Bottom + 20.0
9. Bottom Layout Guide.Top = Center Dummy View.Bottom + 20.0
10. Bottom Layout Guide.Top = Long Button.Bottom + 20.0
11. Bottom Layout Guide.Top = Trailing Dummy View.Bottom + 20.0
12. Short Button.Leading >= Superview.LeadingMargin
13. Long Button.Leading >= Short Button.Trailing + Standard
14. Superview.TrailingMargin >= Long Button.Trailing
15. Leading Dummy View.Width = Center Dummy View.Width
16. Leading Dummy View.Width = Trailing Dummy View.Width
17. Short Button.Width = Long Button.Width
18. Leading Dummy View.Height = 0.0
19. Center Dummy View.Height = 0.0
20. Trailing Dummy View.Height = 0.0

Attributes
Give the buttons a visible background color, to make it easier to see how their frames
change as the device rotates. Additionally, use different length titles for the buttons. The
buttons should be sized based on the longest title.

View Attribute Value

Short Button Background Light Gray Color

Short Button Title Short

Long Button Background Light Gray Color

Long Button Title Much Longer Button Title

Discussion
As you can see, the set of constraints has become complex. While this example is
designed to demonstrate a specific technique, in a real-world app you should consider
using a stack view instead.

In this example, you want the size of the white space to change as the superview’s frame
changes. This means you need a set of equal width constraints to control the white
space’s width; however, you cannot create constraints on empty space. There must be an
object of some sort whose size you can constrain.

In this recipe, you use dummy views to represent the empty space. These views are
empty instances of the UIView class. In this recipe, they are given a 0-point height to
minimize their effect on the view hierarchy.

NOTE

Dummy views can add a significant cost to your layout, so you should use them
judiciously. If these views are large, their graphic context can consume a considerable
amount of memory, even though they don’t contain any meaningful information.
Additionally, these views participate in the view hierarchy’s responder chain. This means
they respond to messages, like hit testing, that are sent along the responder chain. If not
handled carefully, these views can intercept and respond to these messages, creating
hard-to-find bugs.

Alternatively, you could use instances of the UILayoutGuide class to represent the white
space. This lightweight class represents a rectangular frame that can participate in Auto
Layout constraints. Layout guides do not have a graphic context, and they are not part of
the view hierarchy. This makes layout guides ideal for grouping items or defining white
space.

Unfortunately, you cannot add layout guides to a scene in Interface Builder, and mixing
programmatically created objects with a storyboard-based scene can become quite
complex. As a general rule of thumb, it’s better to use storyboards and Interface Builder,
than to use custom layout guides.

This recipe uses greater-than-or-equal constraints to set the minimum spacing around the
buttons. Required constraints also guarantee that the buttons are always the same width,
and the dummy views are also always the same width (though, they can be a different
width than the buttons). The rest of the layout is largely managed by the button’s CHCR
priorities. If there isn’t enough space, the dummy views collapse to a 0-point width, and
the button’s divide the available space amongst themselves (with the standard spacing
between them). As the available space increases, the buttons expand until they reach the
larger button’s intrinsic width, then the dummy views begin to expand. The dummy views
continue to expand to fill any remaining space.

Two Buttons with Size Class-Based Layouts


This recipe uses two different sets of constraints. One is installed for the Any-Any layout.
These constraints define a pair of equal-width buttons, identical to the Two Equal-Width
Buttons recipe.

The other set of constraints are installed on the Compact-Regular layout. These
constraints define a stacked pair of buttons, as shown below.

The vertically stacked buttons are used on the iPhone in portrait orientation. The
horizontal row of buttons is used everywhere else.

Constraints
Lay out the buttons exactly as you did for the Two Equal-Width Buttons recipe. In the Any-
Any size class, set constraints 1 through 6.

Next, switch Interface Builder’s size class to the Compact-Regular layout.


Uninstall constraint 2 and constraint 5, and add constraints 7, 8, and 9 as shown.

1. Short Button.Leading = Superview.LeadingMargin


2. Long Button.Leading = Short Button.Trailing + Standard
3. Long Button.Trailing = Superview.TrailingMargin
4. Bottom Layout Guide.Top = Short Button.Bottom + 20.0
5. Bottom Layout Guide.Top = Long Button.Botton + 20.0
6. Short Button.Width = Long Button.Width
7. Long Button.Leading = Superview.LeadingMargin
8. Short Button.Trailing = Superview.TrailingMargin
9. Long Button.Top = Short Button.Bottom + Standard

Attributes
Give the buttons a visible background color, to make it easier to see how their frames
change as the device rotates. Additionally, use different length titles for the buttons, to
show that the button title does not affect the button’s width.

View Attribute Value

Short Button Background Light Gray Color

Short Button Title short

Long Button Background Light Gray Color

Long Button Title Much Longer Button Title

Discussion
Interface Builder lets you set size-class specific views, view attributes, and constraints. It
allows you to specify different options for three different size classes (Compact, Any, or
Regular) for both the width and the height, giving a total of nine different size classes.
Four of them correspond to the Final size classes used on devices (Compact-Compact,
Compact-Regular, Regular-Compact, and Regular-Regular). The rest are Base size
classes, or abstract representations of two or more size classes (Compact-Any, Regular-
Any, Any-Compact, Any-Regular, and Any-Any).

When loading the layout for a given size class, the system loads the most-specific settings
for that size class. This means that the Any-Any size class defines the default values used
by all views. Compact-Any settings affect all views with a compact width, and the
Compact-Regular settings are only used for views with a compact width and a regular
height. When the view’s size class changes—for example, when an iPhone rotates from
portrait to landscape, the system automatically swaps layouts and animates the change.

You can use this feature to create different layouts for the different iPhone orientations.
You can also use it to create different iPad and iPhone layouts. The size-class-specific
customizations can be as broad or as simple as you want. Of course, the more changes
you have, the more complex the storyboard becomes, and the harder it is to design and
maintain.

Remember, you need to make sure you have a valid layout for each possible size class,
including all the base size classes. As a general rule, it’s usually easiest to pick one layout
to be your default layout. Design that layout in the Any-Any size class. Then modify the
Final size classes, as needed. Remember, you can both add and remove items in the
more specific size classes.

For more complex layouts, you may want to draw out the 9 x 9 grid of size classes before
you begin. Fill in the four corners with the layouts for those size classes. The grid then lets
you see which constraints are shared across multiple size classes, and helps you find the
best combination of layouts and size classes.

For more information on working with size classes, see Debugging Auto Layout.
Types of Errors
Errors in Auto Layout can be divided into three main categories:

• Unsatisfiable Layouts. Your layout has no valid solution. For more information, see
Unsatisfiable Layouts.
• Ambiguous Layouts. Your layout has two or more possible solutions. For more
information, see Ambiguous Layouts.

• Logical Errors. There is a bug in your layout logic. For more information, see
Logical Errors.

Most of the time, the real problem is just determining what went wrong. You added the
constraints you thought you needed, but when you ran the app, things did not turn out as
you had hoped.

Usually, as soon as you understand the problem, the solution is obvious. Remove
conflicting constraints, add missing constraints, and adjust tied priorities so that there is a
clear winner. Of course, getting to the point where you can easily understand the problem
may take some trial and error. Like any skill, it gets easier with practice.

Sometimes, however, things get more complicated. That’s where the Debugging Tricks
and Tips chapter comes in.
Unsatisfiable Layouts
Unsatisfiable layouts occur when the system cannot find a valid solution for the current set
of constraints. Two or more required constraints conflict, because they cannot all be true
at the same time.

Identifying Unsatisfiable Constraints


Often, Interface Builder can detect conflicts at design time. On these occasions, Interface
Builder displays the error in a number of ways:

• All the conflicting constraints are drawn on the canvas in red.


• Xcode lists the conflicting constraints as warnings in the issue navigator.
• Interface Builder displays a red disclosure arrow in the upper right corner of the
document outline.

Click the disclosure arrow to display a list of all the Auto Layout issues in the current
layout.
Interface Builder can often recommend fixes for these issues. For more information,
see Resolving Layout Issues for a View Controller, Window, or Root View in Auto
Layout Help.

NOTE

Although the instant feedback provided by Interface Builder makes it much easier to create
valid layouts, it cannot find all possible layout errors.
For example, Interface Builder detects conflicts only at the canvas’s current size; however,
some conflicts occur only when the root view is stretched or shrunk beyond a certain point
(or when the content expands or shrinks beyond a certain point). Interface Builder cannot
detect these errors.
So, even though you should always fix all the issues that Interface Builder identifies, fixing
the obvious errors is not sufficient. You still need to perform runtime testing across the full
range of screen sizes, orientations, dynamic type sizes, and languages that you intend to
support.

When the system detects a unsatisfiable layout at runtime, it performs the following steps:

1. Auto Layout identifies the set of conflicting constraints.


2. It breaks one of the conflicting constraints and checks the layout. The system
continues to break constraints until it finds a valid layout.
3. Auto Layout logs information about the conflict and the broken constraints to the
console.

This fallback system lets the app proceed, while still attempting to present something
meaningful to the user. However, the effect of breaking constraints can vary greatly from
layout to layout, or even from build to build.

In many cases, the missing constraints may not have any visible effect. The view
hierarchy appears exactly as you expected. In other cases, the missing constraints can
cause entire sections of the view hierarchy to be misplaced, missized, or to disappear
entirely.

It is often tempting to ignore errors when they don’t have an obvious effect—after all, they
don’t change the app’s behavior. However, any change to the view hierarchy or SDK could
also alter the set of broken constraints, suddenly producing an obviously broken layout.

Therefore, always fix unsatisfiable constraint errors when you detect them. To help ensure
that you catch nonobvious errors during testing, set a symbolic breakpoint for
UIViewAlertForUnsatisfiableConstraints.

Preventing Unsatisfiable Constraints


Unsatisfiable constraints are relatively easy to fix. The system tells you when unsatisfiable
constraints occur and provides you with a list of conflicting constraints.

As soon as you know about the error, the solution is typically very straightforward. Either
remove one of the constraints, or change it to an optional constraint.

There are, however, a few common issues worth examining in more detail:

• Unsatisfiable constraints often occur when programmatically adding views to the


view hierarchy.
By default, new views have their translatesAutoresizingMaskIntoConstraints
property set to YES. Interface Builder automatically sets this property to NO when you
begin drawing constraints to a view in the canvas. However, when you’re
programmatically creating and laying out your views, you need to set the property to
NO before adding your own, custom constraints.

• Unsatisfiable constraints often occur when a view hierarchy is presented in a space


that is too small for it.
You can usually predict the minimum amount of space that your view has access to
and design your layout appropriately. However, both internationalization and
dynamic type can cause the view’s content to be much bigger than expected. As the
number of possible permutations grows, it becomes increasingly difficult to
guarantee that your layout will work in all situations.
Instead, you may want to build in failure points, so that your layout fails in a
predictable, controlled manner.
Consider converting some of your required constraints into high-priority optional
constraints. These constraints lets you control where your layout will break when a
conflict occurs.
For example, give your failure point a priority of 999. Under most circumstances, this
high-priority constraint acts as if it were required; however, when a conflict occurs,
the high-priority constraint breaks, protecting the rest of your layout.
Similarly, avoid giving views with an intrinsic content size a required content-hugging
or compression-resistance priority. Typically, a control’s size acts as an ideal failure
point. The control can be a little bigger or a little smaller without having any
meaningful effect on the layout.
Yes, there are controls that should only be displayed at their intrinsic content size;
however, even in these cases it is usually better to have a control that is a few points
off rather than just letting your layout break in unpredictable ways.
Ambiguous Layouts
Ambiguous layouts occur when the system of constraints has two or more valid solutions.
There are two main causes:

• The layout needs additional constraints to uniquely specify the position and location
of every view.
After you determine which views are ambiguous, just add constraints to uniquely
specify both the view’s position and its size.

• The layout has conflicting optional constraints with the same priority, and the system
does not know which constraint it should break.
Here, you need to tell the system which constraint it should break, by changing the
priorities so that they are no longer equal. The system breaks the constraint having
the lowest priority first.

Detecting Ambiguous Layouts


As with unsatisfiable layouts, Interface Builder can often detect, and offer suggestions to
fix, ambiguous layouts at design time. These ambiguities appear as warnings in the issues
navigator, errors in the document outline, and red lines in the canvas. For more
information, see Identifying Unsatisfiable Constraints.

As with unsatisfiable layouts, Interface Builder cannot detect all possible ambiguities.
Many errors can be found only through testing.

When an ambiguous layout occurs at runtime, Auto Layout chooses one of the possible
solutions to use. This means the layout may or may not appear as you expect.
Furthermore, there are no warnings written to the console, and there is no way to set a
breakpoint for ambiguous layouts.

As a result, ambiguous layouts are often harder to detect and identify than unsatisfiable
layouts. Even if the ambiguity does have an obvious, visible effect, it can be hard to
determine whether the error is due to ambiguity or to an error in your layout logic.

Fortunately, there are a few methods you can call to help identify ambiguous layouts. All
of these methods should be used only for debugging. Set a breakpoint somewhere where
you can access the view hierarchy, and then call one of the following methods from the
console:

• hasAmbiguousLayout. Available for both iOS and OS X. Call this method on a


misplaced view. It returns YES if the view’s frame is ambiguous. Otherwise, it returns
NO.

• exerciseAmbiguityInLayout. Available for both iOS and OS X. Call this method on


a view with ambiguous layout. This will toggle the system between the possible valid
solutions.

• constraintsAffectingLayoutForAxis:. Available for iOS. Call this method on a


view. It returns an array of all the constraints affecting that view along the specified
axis.
• constraintsAffectingLayoutForOrientation:. Available for OS X. Call this method
on a view. It returns an array of all the constraints affecting that view along the
specified orientation.
• _autolayoutTrace. Available as a private method in iOS. Call this method on a view.
It returns a string with diagnostic information about the entire view hierarchy
containing that view. Ambiguous views are labeled, and so are views that have
translatesAutoresizingMaskIntoConstraints set to YES.

You may need to use Objective-C syntax when running these commands in the console.
For example, after the breakpoint halts execution, type call [self.myView
exerciseAmbiguityInLayout]into the console window to call the
exerciseAmbiguityInLayout method on the myView object. Similarly, type po
[self.myView autolayoutTrace] to print out diagnostic information about the view
hierarchy containing myView.

NOTE

Be sure to fix any issues found by Interface Builder before running the diagnostic methods
listed above. Interface Builder attempts to repair any errors it finds. This means that if it
finds an ambiguous layout, it adds constraints so that the layout is no longer ambiguous.

As a result, hasAmbiguousLayout returns NO. exerciseAmbiguityInLayout does not


appear to have any effect, and constraintsAffectingLayoutForAxis: may return
additional, unexpected constraints.
Logical Errors
Logical errors are simply bugs. Somewhere, you have an assumption that is faulty.
Perhaps it’s an assumption about how Auto Layout calculates the views’ frames. Perhaps
it’s an assumption about the set of constraints that you’ve created, or the view properties
you’ve set. Perhaps it’s an assumption about how the constraints interact to create
complex behaviors. Regardless, something somewhere does not quite match your mental
model.

Logical errors are the hardest to find. After you eliminate all other possibilities, whatever
remains, however improbable, must be a logical error. However, even after you’ve
determined that you have a bug, you must still discover where, exactly, the faulty
assumption lies.

There are no tools or step-by-step instructions here. Fixing logical errors typically involves
experiments and iterative tests, both to identify the problem and to figure out how to fix it.
There are, however, a few suggestions that may help:

• Review the existing constraints. Make sure you haven’t missed any constraints or
accidentally added unwanted constraints. Make sure all the constraints are attached
to the correct items and attributes.
• Double-check the view frames. Make sure nothing is getting unexpectedly stretched
or shrunk.
This is particularly important for views with invisible backgrounds, like labels or
buttons. It may not be obvious when these items are unexpectedly resized.
One symptom of resizing is that baseline-aligned views no longer line up properly.
This is because the baseline alignment works only when the view is displayed at its
intrinsic content height. If you stretch or shrink the view vertically, the text
mysteriously appears in the wrong location.
• If a control should always match its intrinsic content size, give it a very high content-
hugging and compression-resistance priority (for example, 999).

• Look for any assumptions that you’re making about the layout, and add explicit
constraints to make sure those assumptions are true.
Remember, unsatisfiable layouts are generally the easiest problems to find and fix.
Add additional constraints until you have a conflict, then examine and fix the conflict.

• Try to understand why the given constraints are producing the results that you see.
If you understand it, you’re well on the way to fixing it.
• Experiment with alternative constraints. Auto Layout typically gives you a number of
different solutions for the same problem. Trying an different approach may fix the
problem or at least make it easier to spot the mistake.
Debugging Tricks and Tips
The following topics describe techniques for gathering and organizing information about
your layout, as well as descriptions of some surprising behaviors you may encounter. You
may not need to use these techniques on every layout, but they can help you work your
way through even the most difficult problems.

Understanding the Logs


Information about views can be printed to the console, either because there is an
unsatisfiable layout or because you have explicitly logged constraints using the
constraintsAffectingLayoutForAxis: or constraintsAffectingLayoutForOrientation:
debugging method.

Either way, you can find a lot of useful information in these logs. Here is the sample output
from an unsatisfiable layout error:

1 2015-08-26 14:27:54.790 Auto Layout Cookbook[10040:1906606] Unable


to simultaneously satisfy constraints.
2 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)
3 (
4 "<NSLayoutConstraint:0x7a87b000 H:
[UILabel:0x7a8724b0'Name'(>=400)]>",
5 "<NSLayoutConstraint:0x7a895e30
UILabel:0x7a8724b0'Name'.leading ==
UIView:0x7a887ee0.leadingMargin>",
6 "<NSLayoutConstraint:0x7a886d20 H:[UILabel:0x7a8724b0'Name']-
(NSSpace(8))-[UITextField:0x7a88cff0]>",
7 "<NSLayoutConstraint:0x7a87b2e0 UITextField:0x7a88cff0.trailing
== UIView:0x7a887ee0.trailingMargin>",
8 "<NSLayoutConstraint:0x7ac7c430 'UIView-Encapsulated-Layout-
Width' H:[UIView:0x7a887ee0(320)]>"
9 )
10
11 Will attempt to recover by breaking constraint
12 <NSLayoutConstraint:0x7a87b000 H:[UILabel:0x7a8724b0'Name'(>=400)]>
13
14 Make a symbolic breakpoint at
UIViewAlertForUnsatisfiableConstraints to catch this in the
debugger.
15 The methods in the UIConstraintBasedLayoutDebugging category on
UIView listed in <UIKit/UIView.h> may also be helpful.

This error message shows five conflicting constraints. Not all of these constraints can be
true at the same time. You need to either remove one, or convert it to an optional
constraint.

Fortunately, the view hierarchy is relatively simple. You have a superview containing a
label and a text field. The conflicting constraints set the following relationships:

1. The label’s width is greater than or equal to 400 points.


2. The label’s leading edge is equal to the superview’s leading margin.
3. There is an 8-point space between the label and the text field.
4. The text field’s trailing edge is equal to the superview’s trailing margin.
5. The superview’s width is set to 320 points.

The system attempts to recover by breaking the label’s width.

NOTE

Constraints are written to the console using the Visual Format Language. Even if you
never use the Visual Format Language to create your own constraints, you must be able
to read and understand it to effectively debug Auto Layout issues. For more information,
see Visual Format Language.

Of these constraints, the last one was created by the system. You cannot change it.
Furthermore, it creates an obvious conflict with the first constraint. If you superview is only
320 points wide, you can never have a 400-point-wide label. Fortunately, you don’t have
to get rid of the first constraint. If you drop its priority to 999, the system still tries to
provide the selected width—coming as close as it can while still satisfying the other
constraints.

Constraints based on a view’s autoresizing mask (for example, constraints created when
translatesAutoresizingMaskIntoConstraints is YES) have additional information about
the mask. After the constraint’s address, the log string shows h= followed by three
characters, and v= followed by three characters. A - (hyphen) character indicates a fixed
value, while an & (ampersand) indicates a flexible value. For the horizontal mask (h=), the
three characters indicate the left margin, width, and right margin. For the vertical mask
(v=), they indicate the top margin, height, and bottom margin.

For example, consider the log message:

<NSAutoresizingMaskLayoutConstraint:0x7ff28252e480 h=--& v=--& H:


[UIView:0x7ff282617cc0(50)]>"

This message consists of the following parts:

• NSAutoresizingMaskLayoutConstraint:0x7ff28252e480: The constraint’s class and


address. In this example, the class tells you that it is based on the view’s
autoresizing mask.
• h=--& v=—&: The view’s autoresizing mask. This is the default mask. Horizontally it
has a fixed left margin, a fixed width, and a flexible right margin. Vertically it has a
fixed top margin, a fixed height, and a flexible bottom margin. In other words, the
view’s top left corner and size remain constant when the superview’s size changes.
• H:[UIView:0x7ff282617cc0(50)]: The visual format language description of the
constraint. In this example, it defines a single view with a constant width of 50
points. This description also contains the class and address of any views affected by
the constraint.

Adding Identifiers to the Logs


Although the previous example was relatively easy to understand, longer lists of
constraints quickly become hard to follow. You can make the logs easier to read by
providing every view and constraint with a meaningful identifier.

If the view has an obvious textual component, Xcode uses that as an identifier. For
example, Xcode uses a label’s text, a button’s title, or a text field’s placeholder to identify
these views. Otherwise, set the view’s Xcode specific label in the Identity inspector.
Interface Builder uses these identifiers throughout its interface. Many of them are also
displayed in the console logs.

For the constraints, set their identifier property, either programmatically or using the
Attribute inspector. Auto Layout then uses these identifiers when it prints information to
the console.

For example, here is the same unsatisfiable constraint error with the identifiers set:

1 2015-08-26 14:29:32.870 Auto Layout Cookbook[10208:1918826] Unable


to simultaneously satisfy constraints.
2 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)
3 (
4 "<NSLayoutConstraint:0x7b58bac0 'Label Leading'
UILabel:0x7b58b040'Name'.leading ==
UIView:0x7b590790.leadingMargin>",
5 "<NSLayoutConstraint:0x7b56d020 'Label Width' H:
[UILabel:0x7b58b040'Name'(>=400)]>",
6 "<NSLayoutConstraint:0x7b58baf0 'Space Between Controls' H:
[UILabel:0x7b58b040'Name']-(NSSpace(8))-
[UITextField:0x7b589490]>",
7 "<NSLayoutConstraint:0x7b51cb10 'Text Field Trailing'
UITextField:0x7b589490.trailing ==
UIView:0x7b590790.trailingMargin>",
8 "<NSLayoutConstraint:0x7b0758c0 'UIView-Encapsulated-Layout-
Width' H:[UIView:0x7b590790(320)]>"
9 )
10
11 Will attempt to recover by breaking constraint
12 <NSLayoutConstraint:0x7b56d020 'Label Width' H:
[UILabel:0x7b58b040'Name'(>=400)]>
13
14 Make a symbolic breakpoint at
UIViewAlertForUnsatisfiableConstraints to catch this in the
debugger.
15 The methods in the UIConstraintBasedLayoutDebugging category on
UIView listed in <UIKit/UIView.h> may also be helpful.

As you can see, these identifiers allow you to quickly and easily recognize your
constraints in the log.

Visualizing Views and Constraints


Xcode provides tools that help you visualize the views and the constraints in your view
hierarchy.

To see the views in the simulator:

1. Run the app in the simulator.


2. Switch back to Xcode.
3. Choose Debug > View Debugging > Show Alignment Rectangles. This setting
outlines the edges of your views.

The alignment rectangles are the edges used by Auto Layout. Turning this option on lets
you quickly spot any alignment rectangles that are unexpectedly resized.

If you need even more information, click the Debug View Hierarchy button ( ) in Xcode
debug bar. Xcode then displays an interactive view debugger, giving you a number of
tools for exploring and interacting with the view hierarchy. When debugging Auto Layout
issues, the “Show clipped content” and “Show constraints” options are particularly useful.
Enabling the “Show clipped content” option displays the location of views that may have
accidentally been positioned off screen. Enabling the “Show constraint” option shows all
the constraints affecting the currently selected view. Both options provide a quick sanity
check when things begin behaving oddly.

For more information, see Debug Area Help.

Understanding Edge Cases


Here are a few edge cases that can cause Auto Layout to behave in unexpected ways:

• Auto Layout positions views based on their alignment rectangles, not their frame.
Most of the time, these values are identical. However, some views may set a custom
alignment rectangle to exclude parts of the view (for example, badges) from the
layout calculations.
For more information, see Aligning Views with Auto Layout in UIView Class
Reference.
• In iOS, you can use a view’s transform property to resize, rotate, or move the view;
however, these transformations do not affect Auto Layout’s calculations in any way.
Auto layout calculates a view’s alignment rectangle based on its untransformed
frame.

• A view can display content outside its bounds. Most of the time, views behave
properly and limit their content to their bounds. For performance reasons, however,
this is not enforced by the graphics engine. This means that views (and especially
views with custom drawing) may be drawn at a different size than their frames.
You can identify these bugs by setting the view’s clipsToBounds property to YES or
by verifying the size of the view’s frame.
• The NSLayoutAttributeBaseline, NSLayoutAttributeFirstBaseline, and
NSLayoutAttributeLastBaseline attributes correctly align the text only when all the
views are displayed at their intrinsic content height. If one of the views is stretched
or shrunk vertically, its text may appear in the wrong position.

• Constraint priorities act as global properties across the entire view hierarchy. You
can often simplify your layout by grouping views inside a stack view, a layout guide,
or a dummy view; however, this approach does not encapsulate the contained
views’ priorities. Auto Layout continues to compare priorities inside the group with
priorities outside the group (or even priorities inside other groups).
• Aspect ratio constraints allow horizontal and vertical constraints to interact.
Normally, the horizontal and vertical layouts are calculated separately. However, if
you constrain a view’s height relative to its width, you’ve created a connection
between the vertical and horizontal constraints: They can now affect and conflict
with each other. These interactions greatly increase the complexity of your layout
and can lead to unexpected conflicts between unrelated parts of your layout.
Programmatically Creating Constraints
Whenever possible, use Interface Builder to set your constraints. Interface Builder
provides a wide range of tools to visualize, edit, manage, and debug your constraints. By
analyzing your constraints, it also reveals many common errors at design time, letting you
find and fix problems before your app even runs.

Interface Builder can manage an ever-growing number of tasks. You can build almost any
type of constraint directly in Interface Builder (see Working with Constraints in Interface
Builder). You can also specify size-class-specific constraints (see Debugging Auto
Layout), and with new tools like stack views, you can even dynamically add or remove
views at runtime (see Dynamic Stack View). However, some dynamic changes to your
view hierarchy can still be managed only in code.

You have three choices when it comes to programmatically creating constraints: You can
use layout anchors, you can use the NSLayoutConstraint class, or you can use the Visual
Format Language.

Layout Anchors
The NSLayoutAnchor class provides a fluent interface for creating constraints. To use this
API, access the anchor properties on the items you want to constrain. For example, the
view controller’s top and bottom layout guides have topAnchor, bottomAnchor, and
heightAnchor properties. Views, on the other hand, expose anchors for their edges,
centers, size, and baselines.

NOTE

In iOS, views also have layoutMarginsGuide and readableContentGuide properties.


These properties expose UILayoutGuide objects that represent the view’s margins and
readable content guides, respectively. These guides, in turn, expose anchors for their
edges, centers, and size.
Use these guides when programmatically creating constraints to the margins or to
readable content guides.

Layout anchors let you create constraints in an easy-to-read, compact format. They
expose a number of methods for creating different types of constraints, as shown in
Listing 13-1.
Listing 13-1 Creating layout anchors

1 // Get the superview's layout


2 let margins = view.layoutMarginsGuide
3
4 // Pin the leading edge of myView to the margin's leading edge
5 myView.leadingAnchor.constraint(equalTo:
margins.leadingAnchor).isActive = true
6
7 // Pin the trailing edge of myView to the margin's trailing edge
8 myView.trailingAnchor.constraint(equalTo:
margins.trailingAnchor).isActive = true
9
10 // Give myView a 1:2 aspect ratio
11 myView.heightAnchor.constraint(equalTo: myView.widthAnchor,
multiplier: 2.0).isActive = true

As described in Anatomy of a Constraint, a constraint is simply a linear equation.

The layout anchors have several different methods for creating constraints. Each method
includes parameters only for the elements of the equation that affect the results. So in the
following line of code:

myView.leadingAnchor.constraint(equalTo:
margins.leadingAnchor).isActive = true

the symbols correspond to the following parts of the equation:

Equation Symbol

Item 1 myView

Attribute 1 leadingAnchor

Relationship constraintEqualToAnchor

Multiplier None (defaults to 1.0)

Item 2 margins

Attribute 2 leadingAnchor
Constant None (defaults to 0.0)

The layout anchors also provides additional type safety. The NSLayoutAnchor class has a
number of subclasses that add type information and subclass-specific methods for
creating constraints. This helps prevent the accidental creation of invalid constraints. For
example, you can constrain horizontal anchors (leadingAnchor or trailingAnchor) only
with other horizontal anchors. Similarly, you can provide multipliers only for size
constraints.

NOTE

These rules are not enforced by the NSLayoutConstraint API. Instead, if you create an
invalid constraint, that constraint throws an exception at runtime. Layout anchors,
therefore, help convert runtime errors into compile time errors.

For more information, see NSLayoutAnchor Class Reference.

NSLayoutConstraint Class
You can also create constraints directly using the NSLayoutConstraint class’s
constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant:
convenience method. This method explicitly converts the constraint equation into code.
Each parameter corresponds to a part of the equation (see The constraint equation).

Unlike the approach taken by the layout anchor API, you must specify a value for each
parameter, even if it doesn’t affect the layout. The end result is a considerable amount of
boilerplate code, which is usually harder to read. For example, the code in Listing 13-2
code is functionally identical to the code in Listing 13-1.

Listing 13-2 Directly Instantiating Constraints

1 NSLayoutConstraint(item: myView, attribute: .leading, relatedBy:


.equal, toItem: view, attribute: .leadingMargin, multiplier: 1.0,
constant: 0.0).isActive = true
2
3 NSLayoutConstraint(item: myView, attribute: .trailing, relatedBy:
.equal, toItem: view, attribute: .trailingMargin, multiplier:
1.0, constant: 0.0).isActive = true
4
5 NSLayoutConstraint(item: myView, attribute: .height, relatedBy:
.equal, toItem: myView, attribute:.width, multiplier: 2.0,
constant:0.0).isActive = true
NOTE

In iOS, the NSLayoutAttribute enumeration contains values for the view’s margins. This
means that you can create constraints to the margins without going through the
layoutMarginsGuide property. However, you still need to use the
readableContentGuide property for constraints to the readable content guides.

Unlike the layout anchor API, the convenience method does not highlight the important
features of a particular constraint. As a result, it is easier to miss important details when
scanning over the code. Additionally, the compiler does not perform any static analysis of
the constraint. You can freely create invalid constraints. These constraints then throw an
exception at runtime. Therefore, unless you need to support iOS 8 or OS X v10.10 or
earlier, consider migrating your code to the newer layout anchor API.

For more information, see NSLayoutConstraint Class Reference.

Visual Format Language


The Visual Format Language lets you use ASCII-art like strings to define your constraints.
This provides a visually descriptive representation of the constraints. The Visual
Formatting Language has the following advantages and disadvantages:

• Auto Layout prints constraints to the console using the visual format language; for
this reason, the debugging messages look very similar to the code used to create
the constraints.

• The visual format language lets you create multiple constraints at once, using a very
compact expression.
• The visual format language lets you create only valid constraints.
• The notation emphasizes good visualization over completeness. Therefore some
constraints (for example, aspect ratios) cannot be created using the visual format
language.

• The compiler does not validate the strings in any way. You can discover mistakes
through runtime testing only.

In Listing 13-1, the example has been rewritten using the Visual Format Language:

Listing 13-3 Creating constraints with the Visual Format Language

1 let views = ["myView" : myView]


2 let formatString = "|-[myView]-|"
3
4 let constraints = NSLayoutConstraint.constraints(withVisualFormat:
formatString, options: .alignAllTop, metrics: nil, views: views)
5
6 NSLayoutConstraint.activate(constraints)

This example creates and activates both the leading and trailing constraints. The visual
format language always creates 0-point constraints to the superview’s margins when
using the default spacing, so these constraints are identical to the earlier examples.
However, Listing 13-3 cannot create the aspect ratio constraint.

If you create a more complex view with multiple items on a line, the Visual Format
Language specifies both the vertical alignment and the horizontal spacing. As written, the
“Align All Top” option does not affect the layout, because the example has only one view
(not counting the superview).

To create constraints using the visual format language:

1. Create the views dictionary. This dictionary must have strings for the keys and view
objects (or other items that can be constrained in Auto Layout, like layout guides) as
the values. Use the keys to identify the views in the format string.

NOTE

When using Objective-C, use the NSDictionaryOfVariableBindings macro to


create the views dictionary. In Swift, you must create the dictionary yourself.

2. (Optional) Create the metrics dictionary. This dictionary must have strings for the
keys, and NSNumber objects for the values. Use the keys to represent the constant
values in the format string.
3. Create the format string by laying out a single row or column of items.
4. Call the NSLayoutConstraint class’s
constraintsWithVisualFormat:options:metrics:views: method. This method
returns an array containing all the constraints.
5. Activate the constraints by calling the NSLayoutConstraint class’s
activateConstraints: method.

For more information, see the Visual Format Language appendix.


Size-Class-Specific Layout
Storyboards in Interface Builder by default use size classes. Size classes are traits
assigned to user interface elements, like scenes or views. They provide a rough indication
of the element’s size. Interface Builder lets you customize many of your layout’s features
based on the current size class. The layout then automatically adapts as the size class
changes. Specifically, you can set the following features on a per-size-class basis:

• Install or uninstall a view or control.


• Install or uninstall a constraint.
• Set the value of select attributes (for example, fonts and layout margin settings).

When the system loads a scene, it instantiates all the views, controls, and constraints, and
assigns these items to the appropriate outlet in the view controller (if any). You can access
any of these items through their outlets, regardless of the scene’s current size class.
However, the system adds these items to the view hierarchy only if they are installed for
the current size class.

As the view’s size class changes (for example, when you rotate an iPhone or switch an
iPad app between full-screen and Split View), the system automatically adds items to or
removes them from the view hierarchy. The system also animates any changes to the
view’s layout.

NOTE

The system keeps a reference to the uninstalled items, so they are not deallocated when
they are removed from the view hierarchy.

Final and Base Size Classes


Interface Builder recognizes nine different size classes.

Four of these are the Final size classes: Compact-Compact, Compact-Regular, Regular-
Compact, and Regular-Regular. The Final classes represent actual size classes displayed
on devices.

The remaining five are Base size classes: Compact-Any, Regular-Any, Any-Compact,
Any-Regular, and Any-Any. These are abstract size classes that represent two or more
Final size classes. For example, items installed in the Compact-Any size class appear in
both the Compact-Compact and Compact-Regular size views.

Anything set in a more specific size class always overrides the more general size classes.
Additionally, you must provide a nonambiguous, satisfiable layout for all nine size classes,
even the Base size classes. Therefore, it is typically easiest to work from the most general
size class to the most specific. Select the default layout for your app, and design this
layout in the Any-Any size class. Then modify the other Base or Final size classes as
needed.
Using the Size Class Tool
Select the size class that you are currently editing using Interface Builder’s Size Class
tool. This tool is displayed at the bottom center of the Editor window. By default, Interface
Builder starts with the Any-Any size class selected.

To switch to a new size class, click the Size Class tool. Interface Builder presents a
popover view containing a 3 x 3 grid of size classes. Move your mouse over the grid to
change the size class. The grid shows the selected size class’s name at the top and a
description of the size class (including the devices and orientations it affects) at the
bottom. It also displays a green dot in each size class affected by the current size class.

Any views or constraints added to the canvas are installed only in the current size class.
When deleting items, the behavior varies depending on where and how the items are
deleted.

• Deleting an item from the canvas or document outline removes it from the project
entirely.
• Command-Deleting an item from the canvas or document outline only uninstalls the
item from the current size class.
• When a scene has more than one size class, deleting items from anywhere other
than the canvas or document outline (for example, selecting and deleting constraints
from the Size inspector) uninstalls the item only from the current size class.

• If you have edited only the Any-Any size class, then deleting an item always
removes it from the project.

If you are editing any size class other than the Any-Any size class, Interface Builder
highlights the toolbar at the bottom of the editor window in blue. This makes it obvious
when you’re working on a more specific size class.

Using the Inspectors


You can also modify the size-class-specific settings in the inspectors. Anything that
supports size-class-specific settings appears in the inspector with a small plus icon beside
it.

By default, the inspector sets the value for the Any-Any size class. To set a different value
for a more specific size class, click the plus icon to add a new size class. Select the width,
and then the height, for the size class you want to add.

The inspector now shows each size class on its own line—the Any-Any setting is the top
line, with the more-specific size classes listed below. You can edit the value of each line
independently of the others.

To remove a custom size class, click the x icon at the beginning of the line.

For more information on working with size classes in Interface Builder, see Size Classes
Design Help.
Working with Scroll Views
When working with scroll views, you need to define both the size and position of the scroll
view’s frame within its superview, and the size of the scroll view’s content area. All of
these features can be set using Auto Layout.

To support scroll views, the system interprets constraints differently, depending on where
the constraints are located.

• Any constraints between the scroll view and objects outside the scroll view attach to
the scroll view’s frame, just as with any other view.

• For constraints between the scroll view and its content, the behavior varies
depending on the attributes being constrained:
• Constraints between the edges or margins of the scroll view and its content
attach to the scroll view’s content area.

• Constraints between the height, width, or centers attach to the scroll view’s
frame.

• You can also use constraints between the scroll view’s content and objects outside
the scroll view to provide a fixed position for the scroll view’s content, making that
content appear to float over the scroll view.

For most common layout tasks, the logic becomes far easier if you use a dummy view or
layout group to contain the scroll view’s content. When working in Interface Builder, the
general approach is shown below:

1. Add the scroll view to the scene.


2. Draw constraints to define the scroll view’s size and position, as normal.
3. Add a view to the scroll view. Set the view’s Xcode specific label to Content View.
4. Pin the content view’s top, bottom, leading, and trailing edges to the scroll view’s
corresponding edges. The content view now defines the scroll view’s content area.

REMEMBER
The content view does not have a fixed size at this point. It can stretch and grow to
fit any views and controls you place inside it.

5. (Optional) To disable horizontal scrolling, set the content view’s width equal to the
scroll view’s width. The content view now fills the scroll view horizontally.
6. (Optional) To disable vertical scrolling, set the content view’s height equal to the
scroll view’s height. The content view now fills the scroll view horizontally.
7. Lay out the scroll view’s content inside the content view. Use constraints to position
the content inside the content view as normal.
I M P O R TA N T
Your layout must fully define the size of the content view (except where defined in
steps 5 and 6). To set the height based on the intrinsic size of your content, you
must have an unbroken chain of constraints and views stretching from the content
view’s top edge to its bottom edge. Similarly, to set the width, you must have an
unbroken chain of constraints and views from the content view’s leading edge to its
trailing edge.

If your content does not have an intrinsic content size, you must add the appropriate
size constraints, either to the content view or to the content.

When the content view is taller than the scroll view, the scroll view enables vertical
scrolling. When the content view is wider than the scroll view, the scroll view
enables horizontal scrolling. Otherwise, scrolling is disabled by default.
Working with Self-Sizing Table View Cells
In iOS, you can use Auto Layout to define the height of a table view cell; however, the
feature is not enabled by default.

Normally, a cell’s height is determined by the table view delegate’s


tableView:heightForRowAtIndexPath: method. To enable self-sizing table view cells, you
must set the table view’s rowHeight property to UITableViewAutomaticDimension. You
must also assign a value to the estimatedRowHeight property. As soon as both of these
properties are set, the system uses Auto Layout to calculate the row’s actual height.

1 tableView.estimatedRowHeight = 85.0
2 tableView.rowHeight = UITableViewAutomaticDimension

Next, lay out the table view cell’s content within the cell’s content view. To define the cell’s
height, you need an unbroken chain of constraints and views (with defined heights) to fill
the area between the content view’s top edge and its bottom edge. If your views have
intrinsic content heights, the system uses those values. If not, you must add the
appropriate height constraints, either to the views or to the content view itself.

Additionally, try to make the estimated row height as accurate as possible. The system
calculates items such as the scroll bar heights based on these estimates. The more
accurate the estimates, the more seamless the user experience becomes.

NOTE

When working with table view cells, you cannot change the layout of the predefined
content (for example, the textLabel, detailTextLabel, and imageView properties).
The following constraints are supported:

• Constraints that position your subview relative to the cell’s content view.

• Constraints that position your subview relative to the cell’s bounds.

• Constraints that position your subview relative to the predefined content.


Changing Constraints
A constraint change is anything that alters the underlying mathematical expression of a
constraint (see Figure 17-1). You can learn more about constraint equations in Anatomy of
a Constraint.

Figure 17-1 The constraint equation

All of the following actions change one or more constraints:

• Activating or deactivating a constraint


• Changing the constraint’s constant value
• Changing the constraint’s priority
• Removing a view from the view hierarchy

Other changes, like setting a control’s property, or modifying the view hierarchy, can also
change constraints. When a change occurs, the system schedules a deferred layout pass
(see The Deferred Layout Pass).

In general, you can make these changes at any time. Ideally, most constraints should be
set up in Interface Builder, or programatically created by the view controller during the
controller’s initial setup (for example, in viewDidLoad). If you need to dynamically change
constraints at runtime, it’s usually best to change them when the application’s state
changes. For example, if you want to change a constraint in response to a button tap,
make that change directly in the button’s action method.

Occasionally, you may need to batch a set of changes for performance reasons. For more
information, see Batching Changes.

The Deferred Layout Pass


Instead of immediately updating the affected views’ frames, Auto Layout schedules a
layout pass for the near future. This deferred pass updates the layout’s constraints and
then calculates the frames for all the views in the view hierarchy.

You can schedule your own deferred layout pass by calling the setNeedsLayout method or
the setNeedsUpdateConstraints method.

The deferred layout pass actually involves two passes through the view hierarchy:
1. The update pass updates the constraints, as necessary
2. The layout pass repositions the view’s frames, as necessary

Update Pass
The system traverses the view hierarchy and calls the updateViewConstraints method on
all view controllers, and the updateConstraints method on all views. You can override
these methods to optimize changes to your constraints (see Batching Changes).

Layout Pass
The system traverses the view hierarchy again and calls viewWillLayoutSubviews on all
view controllers, and layoutSubviews (layout in OS X) on all views. By default, the
layoutSubviews method updates the frame of each subview with the rectangle calculated
by the Auto Layout engine. You can override these methods to modify the layout (see
Custom Layouts).

Batching Changes
It is almost always cleaner and easier to update a constraint immediately after the
affecting change has occurred. Deferring these changes to a later method makes the
code more complex and harder to understand.

However, there are times when you may want to batch changes for performance reasons.
This should only be done when changing the constraints in place is too slow, or when a
view is making a number of redundant changes.

To batch a change, instead of making the change directly, call the


setNeedsUpdateConstraints method on the view holding the constraint. Then, override
the view’s updateConstraints method to modify the affected constraints.

NOTE

Your updateConstraints implementation must be as efficient as possible. Do not


deactivate all your constraints, then reactivate the ones you need. Instead, your app must
have some way of tracking your constraints, and validating them during each update pass.
Only change items that need to be changed. During each update pass, you must ensure
that you have the appropriate constraints for the app’s current state.

Always call the superclasses implementation as the last step of your updateConstraints
method’s implementation.

Do not call setNeedsUpdateConstraints inside your updateConstraints method. Calling


setNeedsUpdateConstraints schedules another update pass, creating a feedback loop.
Custom Layouts
Override the viewWillLayoutSubviews or layoutSubviews methods to modify the results
returned by the layout engine.

I M P O R TA N T

If possible, use constraints to define all of your layouts. The resulting layouts are more
robust and easier to debug. You should only override the viewWillLayoutSubviews or
layoutSubviews methods when you need to create a layout that cannot be expressed
with constraints alone.

When overriding these methods, the layout is in an inconsistent state. Some views have
already been laid out. Others have not. You need to be very careful about how you modify
the view hierarchy, or you can create feedback loops. The following rules should help you
avoid feedback loops:

• You must call the superclass’s implementation somewhere in your method.


• You can safely invalidate the layout of views in your subtree; however, you must do
this before you call the superclass’s implementation.
• Don’t invalidate the layout of any views outside your subtree. This could create a
feedback loop.

• Don’t call setNeedsUpdateConstraints. You have just completed an update pass.


Calling this method creates a feedback loop.
• Don’t call setNeedsLayout. Calling this method creates a feedback loop.
• Be careful about changing constraints. You don’t want to accidentally invalidate the
layout of any views outside your subtree.
Visual Format Language
This appendix shows how to use the Auto Layout Visual Format Language to specify
common constraints, including standard spacing and dimensions, vertical layout, and
constraints with different priorities. In addition, this appendix contains a complete
language grammar.

Visual Format Syntax


The following are examples of constraints you can specify using the visual format. Note
how the text visually matches the image.

Standard Space
[button]-[textField]

Width Constraint
[button(>=50)]

Connection to Superview
|-50-[purpleBox]-50-|

Vertical Layout
V:[topField]-10-[bottomField]

Flush Views
[maroonView][blueView]

Priority
[button(100@20)]

Equal Widths
[button1(==button2)]

Multiple Predicates
[flexibleButton(>=70,<=100)]

A Complete Line of Layout


|-[find]-[findNext]-[findField(>=20)]-|

The notation prefers good visualization over completeness of expressibility. Most of the
constraints that are useful in real user interfaces can be expressed using visual format
syntax, but there are a few that cannot. One useful constraint that cannot be expressed is
a fixed aspect ratio (for example, imageView.width = 2 * imageView.height). To create
such a constraint, you must use
constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant:.

Visual Format String Grammar


The visual format string grammar is defined as follows (literals are shown in code font; e
denotes the empty string).

Symbol Replacement rule

(<orientation>:)?
(<superview><connection>)?
<visualFormatString>
<view>(<connection><view>)*
(<connection><superview>)?
<orientation> H|V

<superview> |

<view> [<viewName>(<predicateListWithParens>)?]

<connection> e|-<predicateList>-|-

<predicateList> <simplePredicate>|<predicateListWithParens>

<simplePredicate> <metricName>|<positiveNumber>

<predicateListWithParens> (<predicate>(,<predicate>)*)

(<relation>)?(<objectOfPredicate>)
<predicate>
(@<priority>)?

<relation> ==|<=|>=

<objectOfPredicate> <constant>|<viewName> (see note)

<priority> <metricName>|<number>

<constant> <metricName>|<number>

Parsed as a C identifier. This must be a key


<viewName> mapping to an instance of NSView in the
passed views dictionary.

Parsed as a C identifier. This must be a key


<metricName> mapping to an instance of NSNumber in the
passed metrics dictionary.

<number> As parsed by strtod_l, with the C locale.

NOTE

For the objectOfPredicate production, viewName is acceptable only if the subject of the
predicate is the width or height of a view. That is, you can use [view1(==view2)] to
specify that view1 and view2 have the same width.

If you make a syntactic mistake, an exception is thrown with a diagnostic message. For
example:

1 Expected ':' after 'V' to specify vertical arrangement


2 V|[backgroundBox]|
3 ^
4
5 A predicate on a view's thickness must end with ')' and the view
must end with ']'
6 |[whiteBox1][blackBox4(blackWidth][redBox]|
7 ^
8
9 Unable to find view with name blackBox
10 |[whiteBox2][blackBox]
11 ^
12
13 Unknown relation. Must be ==, >=, or <=
14 V:|[blackBox4(>30)]|
15 ^
Document Revision History
This table describes the changes to Auto Layout Guide.

Date Notes

2016-03-21 Added Changing Constraints chapter.

Added advanced recipes to the cookbook. Incorporated other


2015-12-10
minor updates.

Updated to include information about using Auto Layout with


2015-09-16
iOS size classes. Added many Auto Layout examples.

2013-09-18 Updated to describe Auto Layout in Xcode 5.

2012-09-19 Added to iOS Library. Added links to WWDC videos.

2012-02-16 Corrected minor code error.

New document that describes the constraint-based system


2011-07-06
for laying out user interface elements.

You might also like