The layout of our user interfaces need to respond to both external and internal changes. External changes occur when our view’s bounds change and we have to adjust its contents to match. Autorotation is the most common cause of external changes in an iOS app; however, there are other sources of change. Switching between a 3 1/2- and a 4-inch phone will change the view size. The in-call and audio recording banners will also reduce the view size when they are displayed.
Internal changes occur when the size of our view’s content changes, forcing us to adjust the rest of its layout. These changes can occur when text or images change. Similarly, switching languages can also trigger internal changes, because this changes all the text. It may even change the reading direction. For example, switching from a left-to-right language like English, to a right-to-left language like Arabic may require radical changes to the layout. Finally, in iOS 7, internal changes will also occur whenever the user switches the font size of dynamic type.
Traditionally, iOS apps used autoresizing masks to automate some of these layout changes. Unfortunately, autoresizing masks only addressed a relatively small set of possible changes. This often meant we needed to supplement autoresizing masks with programmatic changes to our layout.
Auto Layout attempts to solve this problem by providing a powerful, declarative, rules-based layout engine. Instead of defining a view’s location by setting its frame, bounds, or center, we now create a number of constraints that define its position relative to other views.
Now, don’t get me wrong. Learning Auto Layout is hard. There are basically two steps to mastering Auto Layout. First, you need to master the logic behind the constraints. Then you need to master the API.
Fortunately, this is no different from any other programming task. Unfortunately, declarative, constraint-based layouts require a different type of logic than our typical procedural or object-oriented programming. Until you use it enough to strengthen those mental muscles, it will probably feel foreign and uncomfortable. The good news is, if you mastered one type of programming logic, you can easily master another.
Basically, Auto Layout uses linear equations to define each view’s position relative to its neighbors. All the linear equations use the following format:
view_1.attribute_1 = view_2.attribute_2 * multiplier + constant
Imagine we have two buttons. To set the standard spacing between these buttons, we would typically use the following equation:
button_1.trailingEdge = button_2.leadingEdge * 1.0 + 8.0
The trick to using Auto Layout is to define a set of constraints that uniquely defines the position and size of each view. In theory, this means we need to provide two horizontal and two vertical constraints for each view. In practice, many controls have intrinsic sizes, which means we only need to define their position. On the other hand, we can also create constraints that use inequalities, or create optional constraints with varying priorities, requiring additional constraints.
When it comes to the API, we have three options. We can programmatically set the constraints using standard method calls, we can programmatically set the constraints using the visual formatting language, or we can add the constraints in Interface Builder.
Writing constraints by hand is both tedious and error-prone. The visual formatting language can help, by letting us define multiple constraints in a single line. Unfortunately, it introduces its own problems, because the compiler cannot check the syntax of the formatting strings.
Much like laying out a view hierarchy, in anything but the most trivial cases, it is easier and quicker to design all the constraints in Interface Builder.
Now, if you tried using Auto Layout inside Interface Builder in Xcode 4, please give it another look in Xcode 5. Apple’s initial implementation tried to be a bit too helpful. As a result, it often got in our way or overwrote our existing constraints.
In Xcode 5, Interface Builder no longer tries to help us out. This means we now have to do everything ourselves, but it actually makes the tools a lot more useful and manageable. Xcode 5’s also includes excellent error checking and visual feedback, which we don’t get when programmatically creating our constraints. This both informs us of ambiguous and conflicting layouts, and gives advice on how to solve the problem.
While learning Auto Layout will require a bit of effort, it is well worth the time and energy. Again, it comes down to efficiency. Once you become familiar with the logic and the tools, setting up the constraints for complex layouts can be done both quickly and easily, and the visual feedback means we’re less likely to have bugs in our constraints. Furthermore, creating layouts that adapt to dynamic type and language changes virtually requires Auto Layout.
Much like ARC and Storyboards, Apple is clearly positioning Auto Layout as the way of the future. By adopting Auto Layout now, we are ensuring that our code can more easily support whatever changes are coming down the line.