Mar 11 2013

iOS Autolayout: Fun Facts and Tips

Editor’s note: This post originally appeared on the the blog of Joe Conway, co-author of iOS Programming:The Big Nerd Ranch Guide.

Have you ever stared at the tracking information for your new MacBook, hitting refresh every five minutes? It is infuriating. But the fact that a MacBook can come off the assembly line somewhere in China and end up at my doorstep a few days later is a serious work of mathematical art.

Consider all of the issues in optimizing the pickup and delivery of your next MacBook: a company like FedEx has to factor in the number of trucks they have, the amount of goods that can fit on those trucks, the cost of gas, the distance from their nearest distribution center to your doorstep and so on. If they were to just shoot from the hip and deliver things in whatever order their manager thinks is best, they would run out of money or your shiny laptop wouldn’t show up. Instead, they have to rely on a field of math called linear programming to determine the way they operate.

Linear programming (which has nothing to do at all with programming in the way we think of it, but instead, is a synonym for linear optimization for math folks) is used to solve equations for which there are a lot of variables that depend on each other. FedEx needs to minimize some of these variables (like the amount they spend on gas) and maximize some others (like how many items can be delivered in a day).

Because there are so many variables involved and each of their ranges is so vast, a human being couldn’t find the optimum value for each of the variables to minimize their costs and maximize their production, but a linear objective function can. A human being can set up some constraints for each variable, like a truck can travel up to 200 miles in a day and gas costs $3.50 today. Each of these constraints is a simple linear equation, like travel < = 200.0 and gas = 3.50. A linear objective function is a combination of all of these equations solved at once that finds the optimum value for each unsolved variable.

What does this have to do with autolayout? The autolayout system is one big linear objective function. Each NSLayoutConstraint you create is just one linear equation in a linear objective function. For example, one constraint could be view.left = anotherView.right + 10 and another could be view.width >= 20.

When a view is being laid out, the linear objective function is evaluated to determine a minimum and maximum value for each part of a view’s frame. A valid set of constraints for autolayout is when every variable has a maximum equal to its minimum; that is, there is only one solution to satisfy every constraint in a view hierarchy. (If there is more than one solution to the function, you have an ambiguous layout, if there isn’t a solution, you have conflicting constraints and you get an exception.)

Because of the way linear objective functions are evaluated, there isn’t an order that the constraints are computed in. So if that was how you were approaching constraints, get that out of your head: an equation like view.top = anotherView.bottom + 10 doesn’t mean that you find the value of anotherView’s bottom first and add 10 to get view’s top. It is just one more equation that has to be satisfied for your layout to work; both of these variables can change depending on the other constraints.

Of course, the math behind all of this is really complicated. The implementation of autolayout is less complicated, but let’s not pretend it is easy at first. So, here is what I recommend:

Use autolayout only when you need to

Autoresizing masks aren’t deprecated or obsolete. Just like Core Data didn’t make archiving obsolete nor did blocks make delegation useless, you will still use autoresizing masks. Many iOS applications—while they may have pretty artwork—are pretty simple, layout-wise. You have a table, it has some cells, there is some stuff in the cells, there are some buttons above it and maybe a duck. Well, probably not a duck, but do you really need autolayout to keep the table view on the bottom of the screen and the buttons as a header on top? Does a cell with two text fields need autolayout to keep them aligned with each other? Will rotating the device, putting into a navigation controller or running it on an iPhone 5 really change the layout of this view? No. So don’t overkill it with autolayout.

The keyboard shortcut you need to know about

Manipulating the layout of a user interface in an XIB is, let’s face it, a cruel joke. Once a view is dropped into an XIB, you get all kinds of constraints that make sense for the position of that view where you dropped it—but not where you eventually want it. On top of that, Xcode enforces the constraints that apply to your views when manipulating them in the XIB—got a label that is pinned to match the size of the button below it? Xcode may not let you drag the resizing controls for that label.

Unless you hold the command key. The most useful but under-documented feature of autolayout is holding the command key while manipulating views in an XIB file. While holding the command key, Xcode lets you break any constraint applied to a view while resizing it.

Stop thinking about frames

When laying out an interface, we typically think about the frame of a view. Stop. The frame of a view is an absolute position and size. That doesn’t make sense when a view should lay itself out relative to the rest of the screen. Want to think about the size of a view? Think about its intrinsic content size. Want to think about the position of a view? Think about its offset from other views in the interface. A button doesn’t have a frame of {20, 40, 200, 40}, no, it is 10 points below a label, centered on the Y axis of its superview and wants to fit its title comfortably.

Change constants, not constraints

One of the more useful (and difficult) features of autolayout is the ability to make dynamic user interfaces. If your model changes and a new button needs to move into place, don’t delete the current constraint and create a new one. Finding constraints at runtime is not straightforward, but modifying the constant of a constraint is very simple. If a button needs to slide in from the right side of the screen, create a constraint where initially button.left = superview.left + 400. When it comes time to slide it in, change the constant so that the equation is button.left = superview.left + 200. As an added bonus, animation comes for free:

[[self buttonEdgeConstraint] setConstant:200];
[UIView animateWithDuration:0.5 animations:^{
[[self button] layoutIfNeeded];
}];

Understand the limitations and bugs

Right now, setting up constraints in an XIB file for a UITableViewCell doesn’t do what you expect it to do: each constraint thinks that the superview is the instance of UITableViewCell, not the cell’s contentView. This means that you will never get what you expect. Instead, turn off autolayout for a UITableViewCell XIB and either set up constraints programmatically or use autoresizing masks.

When modifying an XIB, Xcode won’t let you set up constraints that are invalid (for the most part). That means if you have a constraint you don’t want, you may have to add another constraint before you can delete it.

The thickness of the constraint line in the XIB is your key: a thin blue line is a required constraint, whereas the thicker blue line is a user constraint. Required constraints can’t be deleted, otherwise the layout would become invalid. When a set of constraints over-qualifies a view’s frame, the constraints that aren’t necessary automatically become user constraints that can be deleted. For example, if you plop a text field onto the screen, it may set up a left and right edge constraint. If you don’t want the right edge constraint, pin the width of the text field—this makes the right edge and width constraints redundant. Then you can delete the right edge constraint and the width constraint will become required.

6 Comments

  1. Gregory Hill

    Nice article. I recently completed a project that made extensive use of constraints. It was not easy, to say the least. A lot of painful lessons.

    I’ve found that even when you “over constrain” an object, the redundant constraints don’t automatically get promoted to user constraints. You have to select them, go to the Size Inspector, and then manually promote the constraint there.

    And the IB interface for managing constraints is brutal. The Xcode team definitely needs to up the ante there. The hoops you have to jump through to manage multiple constraints is mind-numbing.

    And … is it possible to turn auto-layout off for individual elements in a layout? I thought that was a project-level switch.

    The power behind auto-constraints is impressive. I think after a couple more enhancement iterations in IB, it will become an extremely useful tool for many iOS developers. I hope the Xcode team keeps pushing the envelope.

  2. Tom

    Just a thought, having read of the cost of using autolayout vs manually setting up – if the complexity isn’t necessarily going to get much higher fro what the developers create, over time, won’t faster chips (eg A7 in iPhone 5s) help reduce lag/the issue? Will it be preferred if/when we see new dimensions for iPhones/iPads?

    • Alex Silverman

      @Tom: yeah, I agree with what you are saying. The advantages of using auto-layout (e.g. quickly supporting new screen sizes) will outweigh the disadvantages more and more as the processors get faster.

  3. Christian Keur

    Tom – with Xcode 5, Auto Layout has become much much easier to work with. Because of this, I highly recommend that developers start using Auto Layout throughout their projects (and I suspect that many will).

    There are already 2 different sizes iPhones, and with Universal applications, you have 3 sizes to consider (3.5″ iPhone, 4.0″ iPhone, and iPad). Additionally, some of Apple’s built in UI elements (UISegmentedControl for example) are sized differently in iOS 6 compared to iOS 7. For these reasons, as well as others, it is strongly recommended to make use of Auto Layout these days.

    Regarding the performance – you are right that as devices become more powerful, the ‘cost’ of using Auto Layout will start to melt away. And at the end of the day, Auto Layout is plenty fast for just about all needs. Use it, and only if you notice slow down due Auto Layout should you consider optimizations.

  4. Bharath

    Thanks for this article. I have started looking into Auto Layouts very recently and I am liking it . Looks like Apple is coming up with devices with various sizes & hence they are encouraging developers to use Auto Layouts.
    I am trying to create UI similar to ios mail app . Would you recommend using auto layouts for this or the traditional struts & springs approach ? Are there any sample apps (creating using Auto Layouts ) which has UI as complex as mail app ?

  5. Krishnan

    Thanks for the write up..Cleared lot of doubts regarding autolayout .

Leave a Comment

Join the discussion. Do not worry, your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>