Beginning Auto Layout in iOS 6: Part 2/2

Update note: Check out our newer version of this tutorial, updated to Swift and iOS 8: Beginning Auto Layout Tutorial in Swift: Part 2. This tutorial is an abbreviated version of one of the chapters from our new book iOS 6 By Tutorials. Matthijs Hollemans wrote this – the same guy who wrote the iOS […] By Matthijs Hollemans.

Leave a rating/review
Save for later
Share

Learn Auto Layout in the iOS 6 SDK!

Update note: Check out our newer version of this tutorial, updated to Swift and iOS 8: Beginning Auto Layout Tutorial in Swift: Part 2.

This tutorial is an abbreviated version of one of the chapters from our new book iOS 6 By Tutorials. Matthijs Hollemans wrote this – the same guy who wrote the iOS Apprentice Series. Enjoy!

In part 1 of this tutorial you saw that the old “struts-and-springs” model for making user interfaces cannot easily solve all layout problems. The new Auto Layout feature from iOS 6 is the solution, but because this technology is so powerful it is also a bit more tricky to use.

In this second part and final part of the tutorial series, you’ll continue learning all about constraints and how to apply them!

As bold as a user constraint

Maybe you noticed that some of the T-bars in the canvas are thicker than others. The bold ones are called user constraints, and unlike the thin ones you can delete them. However, when you delete a user constraint, Interface Builder will often put a non-deletable constraint in its place. You will soon see why.

In the Document Outline, user constraints have a blue icon:

User constraints document outline

Select the Vertical Space (40) constraint and tap the Delete key on your keyboard. The T-bar between the two buttons disappears and is replaced by a new Vertical Space constraint that goes all the way to the bottom:

After deleting user constraint

This new constraint has a purple icon and does not have a bold line, meaning that you cannot delete this one. The two buttons are no longer connected vertically, although they are still left-aligned due to the Leading Alignment constraint.

Why does this happen? Why does Interface Builder attach a new Vertical Constraint to the button, even though you just told it to delete such a constraint? The answer is this:

For each view there must always be enough constraints to determine both its position and size.

That is the most important rule to remember when it comes to using Auto Layout. If there aren’t enough constraints, then Auto Layout will be unable to calculate where your views should be positioned or how big they should be. Such a layout is considered to be invalid. You will see examples of such invalid layouts later on.

Interface Builder tries very hard to prevent you from making layouts that are invalid. The size of these two buttons is known because buttons know how big they should be, based on their text, background image, and so on – intrinsic content size, remember? So that’s not a problem. The X-position of the top button is also known because its left edge is aligned with the bottom button, and the bottom button is always horizontally centered. The only unknown is the Y-position.

Previously, the two buttons were connected with a Vertical Space. That was enough to determine the Y-position of the top button. But if you delete that Vertical Space, then the top button has nothing to anchor it vertically in the view. It cannot just float there because then Auto Layout has no way to determine what its Y-coordinate should be.

To prevent this from happening, Interface Builder needs to “pin” the button somewhere and the bottom edge is closest.

Pin all the buttons

Funnily enough, if you run the app and flip to landscape, it still seems to work. The screen looks exactly the same as it did before. That is true, but your design is fundamentally different: both buttons are now connected to the bottom of the window. This means that if the bottom button moves, the top one doesn’t move with it. (Note that either solution is fine, it just depends on what you want your app to do. But in this example, you want to have a vertical connection between the two buttons.)

To illustrate this, select the Vertical Space constraint between the lower button and the screen’s edge. Go into the Attributes inspector. It’s Constant should currently read “Auto”, and Standard is checked because this is a standard margin space. Change it to 40.

Because the buttons are not connected, only the lower button moves upward; the top button stays put:

Only bottom button moves up

Notice that changing the Constant value of the constraint promoted it to a bold “user” constraint.

Needles and pins

Let’s connect the two buttons again. So far you have made constraints by dragging the buttons on the canvas, but you can also make them afterwards. Hold down the Cmd key and click both buttons to select them. From the Editor menu, choose Pin\Vertical Spacing.

You can also use the little panel in the bottom-right corner to make this constraint:

Shortcut menu pin

It pops up the following menu:

Pin menu

Regardless of the method you choose, this adds a new constraint between the two buttons:

Pin vertical spacing

The new constraint is a Vertical Space constraint with a Constant of 20 points. That is because the distance between the two buttons was 20 points at the time you made this connection.

Notice that the old Vertical Space from the upper-most button to the bottom edge is still there. This constraint – the one that says Vertical Space (104) – is no longer needed, so delete it.

Previously when you deleted a blue constraint, a purple one took its place. Now that does not happen, because the remaining constraints are sufficient to position all the views. Interface Builder only adds new constraints when the existing ones are no longer adequate.

You should now have the following constraints:

Restored constraints

Select the bottom Vertical Space (by clicking on the canvas) and change its Constant from 40 back to Standard. This should not only move the bottom button downwards, but the top button as well, because they are connected again.

A little runtime excursion

You’ve seen a bit of the basics now: you know how to place controls using the guides, how to align them relative to one another, and how to put space between controls. Over the course of this tutorial you will also use the other options from the Align and Pin menus.

Playing with this in Interface Builder is all well and good, but let’s see how this works at runtime. Add the following method to ViewController.m:

- (IBAction)buttonTapped:(UIButton *)sender
{
    if ([[sender titleForState:UIControlStateNormal] isEqualToString:@"X"])
        [sender setTitle:@"A very long title for this button" 
                forState:UIControlStateNormal];
    else
        [sender setTitle:@"X" forState:UIControlStateNormal];
}

This simply toggles between a long title and a short title for the button that triggered the event. Connect this action method to both of the buttons in Interface Builder: Ctrl-drag from each button to File’s Owner and select buttonTapped: in the popup.

Run the app and tap the buttons to see how it behaves. Perform the test in both portrait and landscape orientations.

Long and short titles

Regardless of which button has the long title and which has the short title, the layout always satisfies the constraints you have given it:

  • The lower button is always center-aligned in the window, horizontally.
  • The lower button always sits 20 points from the bottom of the window.
  • The top button is always left-aligned with the lower button.

That is the entire specification for your user interface.

For fun, select both buttons in Interface Builder and from the Align menu pick Right Edges. Now run the app again and notice the differences.

Repeat, but now choose Align\Horizontal Centers. That will always center the top button with respect to the bottom button. Run the app and see how the buttons act when you tap them.

Contributors

Over 300 content creators. Join our team.