This tutorial is an excerpt from our book series iOS App Development for Non-Programmers, available in the iBookStore for the iPad, and on Amazon.
Part 1 discusses the two layout options, then dives in on springs and struts. Part 2 discusses the new Auto Layout option available in iOS 6 and later. Part 3 takes tutorial on Auto Layout to the next level!
Now that you have a basic understanding of how to set constraints on a single control, it’s time to learn how to set constraints on multiple controls in relation to the parent view and each other.
If you haven't already downloaded the sample code for part 1 and part 2 of this tutorial, click on the following link:
Tutorial Samples
Figure 8.43 Drop an image view on the scene.
This adds four constraints to the scene, which you can see in the scene itself as well as the Size Inspector as shown in Figure 8.44:
Figure 8.44 Four constraints are created for the image view.
The width and height constraints are getting added because there is no default guide line against which the right and bottom sides of the image view can be placed. This is perfectly acceptable.
The top and left sides of the image view are positioned against guide lines, so their spacing is set to Default.
Go to the Size Inspector (second button from the right in the Inspector toolbar) and change the Width to 150 and the Height to 150.
When you do this, it changes the width and height constraints to the new values.
Figure 8.45 The image is set in the image view.
Figure 8.46 Drop a text view on the scene.
This adds the four constraints shown in Figure 8.47:
Figure 8.47 Four constraints are created for the text view.
To do this, grab the resizing handle at the bottom of the text view and drag it downward. When the guide line appears (
Figure 8.48 Align the bottom of the text view with the bottom of the image view.
Doing this removes the hard-coded height constraint and replaces it with a new Align Bottom to: Image View - OliverCast.png constraint.
Figure 8.49 Adjust the width of the text view.
Next, hold the Control key down, click the text view and drag down to the tvwTestoutlet in the ViewController.h file. When the Connect Outlet popup appears (Figure 8.50), release the mouse key to create the connection to the outlet.
Figure 8.50 Connect the text view to the tvwTest outlet.
Now let’s see how these controls look at run time. Click Xcode’s Run button, and when the App appears in the Simulator, it looks just as it does at design time (except there is descriptive text in the text view).
Figure 8.51 The text view & image view in landscape mode
This is exactly what is specified by the constraints, but not exactly what we want. There is a lot of empty space in the middle of the view that should be filled by increasing the width of the image view and text view. Let’s fix that now.
Figure 8.52 Interface Builder Auto Layout buttons
Click the center button in this button group. As you can see in Figure 8.53, this provides a variety of Pin options.Figure 8.53 Create a Horizontal Spacing constraint.
Select Horizontal Spacing to pin the spacing between the image view and text view to its current value of zero points. This creates a new Horizontal Space constraint that you can see in the Document Outline pane (Figure 8.54), although oddly enough, it doesn’t appear in the Size Inspector.
Figure 8.54 The new Horizontal Space constraint
Figure 8.55 Zero space between the image view and text view.
In just a bit, you will learn how to evenly divide the available space between the image view and text view, but for now, we’re going to fix a problem with conflicting constraints.
Did you notice that when you rotated the App in the Simulator, the warnings shown in Figure 8.56 were displayed in the Console?
Figure 8.56 Conflicting constraints warning
Even though the final result of the resizing and positioning of controls was correct, the Auto Layout system found conflicts in the constraints.
The message at the top of Figure 8.56 says: “Unable to simultaneously satisfy constraints.” The next paragraph states “Probably at least one of the constraints in the following list is one you don’t want.” Further down, it lists the group of constraints in which there is a conflict, and near the bottom it tells you which constraint it broke to try and recover from the conflict.
This is a great feature of Auto Layout. Even though there are conflicting constraints, it does its best to come up with a best guess for a solution by breaking one of the conflicting constraints.
Looking through the list of constraints should give you a pretty good idea where the conflict lies. The constraints are displayed in the syntax of Apple’s Visual Format Language. Here is some of the basic syntax of this language (for more information, check out the topic Visual Format Language in the Apple documentation):
For example, look at the second half of the first constraint:
H:[UITextView:0x79f3000(130)]
From this information you can derive that this is the text view’s width constraint. As you look through the other constraints, it’s pretty easy to see the problem. The constraints dictate that:
When the device is in portrait orientation, all of these constraints can be satisfied. However, when the device is rotated to landscape orientation and the view becomes wider, not all of these constraints can be satisfied. For that reason, the Auto Layout system decided to break the image view’s width constraint:
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x892e8f0 H:[UIImageView:0x892e790(150)]>
Even if you agree with the decision made by the Auto Layout system, you should still fix the conflict so your constraints are simplified and efficient. Let’s do that now.
Figure 8.57 Set the Relation to Greater Than or Equal.
Let’s look at another example that will provide another opportunity to resolve a constraint conflict. In this example, you will make the image view and text view equal in width.
Figure 8.58 The image view’s width constraint
Figure 8.59 Resize the text view’s width to 140 points.
In the Xcode menu, select Editor > Pin > Widths Equally. When you do this, a new equal widths constraint is added to the view (Figure 8.60). Notice there is an equal sign inside a circle under the image view and the text view representing the equal width constraint.
Figure 8.60 The new equal widths constraint.
Figure 8.61 The text view and image view are equal widths.
This works exactly as it should, but you may have noticed there were constraint conflict errors displayed in the Console again. Let’s take a closer look to see how these can be fixed.
Figure 8.62 shows the constraint debugging information displayed in the Console.
Figure 8.62 The new set of constraint conflicts
Can you spot the problem? Ultimately, this is very similar to the constraint conflicts you saw earlier. The text view is constrained to be 140 points and the image view is constrained to be the same size as the text view. This is fine when in portrait mode, but it’s not possible in landscape mode.
When you fixed the problem last time, you changed the width constraint from Equal toGreater Than or Equal. This time we’re going to do something different.
Figure 8.63 The Width constraints
Click on the Text View’s Width constraint in the Document Outline pane and then press Delete to delete it.
As you lay out your own user interfaces in Xcode using Auto Layout, I recommend looking very carefully at the constraints that have been added to your scenes and remove those that are not necessary.
Kevin McNeish
Author: iOS App Development for Non-Programmers book series
Twitter: @kjmcneish