Auto Layout & Interface Builder Tutorial: Solving some common problems

Interface Builder is Best?

In their 2012 WWDC sessions on Auto Layout, Apple recommends that the primary method for creating interfaces using Auto Layout should be Interface Builder.

IB has a few quirks (some would say large number of flaws) which can make it seem like black magic trying to bend it to your will. It leaves you afraid of making any adjustments once you’ve got something working.

As Jonathan Wight put it:

“When autolayout works it works fantastically well. Now I will back away slowly and not touch anything!”

The first thing to remember: Interface Builder won’t let you create an interface that has ambiguous constraints. Therefore, when you drop a control onto your interface, IB will automatically add all the constraints required. For views which have intrinsic content sizes like a button, this may show only two constraints. For other views: there will probably be four constraints.

The Issues

This causes some problems:

  1. A constraint has been added that you don’t want, and can’t get rid of.
  2. You’ve added a constraint which the system immediately replaces with a constraint which doesn’t meet your requirements.

Solving Problem 1: Constraints that hang around like a bad smell

Remember an easy way to see the constraints that apply to a particular view can be seen by selecting the view and then viewing the “size insepctor” (opt-cmd-5)

Screenshot of size insepctor showing constraints

Once constraints are added, it can be tricky to replace them with the constraints that you actually require.

The first thing to try is just to try deleting the constraint that you don’t require. Usually this doesn’t work, but if you’ve been making changes, it sometimes seems that IB ‘forgets’ to clean up after itself, and remove constraints that it added but which are no longer required.

Select the constraint, and press ‘delete’. Sometimes this doesn’t work even though the constraint is ‘deletable’. In these cases, try reducing the priority of the unwanted constraint to ’1′ and then deleting it.

Setting the priority of a constraint to 1 in IB

In the event that this doesn’t work (highly likely), then IB is protecting you from yourself.

Justin Williams puts it well in his post on Autolayout (emphasis added):

“What frustrates me about setting constraints with Interface Builder is its instance on adding more constraints automatically for me, even if I don’t want/need them. I’d love some sort of button or setting I can click to tell Interface Builder to back off and just let me handle everything.”

Unfortunately that doesn’t exist (yet?) so you currently have to resort to alternative means:

The two solutions are:

  • Ignore IB’s constraints, add your own constraints and hope that by the time you’ve finished, your constraints are enough to satisfy IB, and you can delete the extraneous constraints using the methods described above.
  • Create outlets for any of the IB constraints that you don’t want and remove them in code.

The first solution often invokes our second problem.

Solving Problem 2: IB thinks its constraints are better than mine

You ignore IB, merrily adding your constraints, only to look at the list of constraints to find that IB has removed your carefully planned out constraints and replaced them with something else, which may satisfy the layout in its current state, but doesn’t work when your layout is changed in ways IB can’t possibly imagine.

The first thing to try is promoting an IB generated constraint (they show up as purple) to a user constraint – in the size insepctor, click on the constraint and choose “Promote to user constraint”. This should tell IB that his constraint is important to you, and (in theory) as long as you don’t directly contradict the constraint, IB should leave it alone.

Promoing a constraint to user constraint in IB

The final solution to this problem could be considered the “nuclear option”: Let Interface Builder do what it likes, then create outlets to any constraints that you don’t want, and remove them in code.

An outlet created from an IB constraint

This works, but you’re quite likely to end up with an ambiguous layout and/or having to add additional constraints in code. You lose the benefits of having your interface all nicely set up in IB.

There are no easy answers at the moment. Personally, I’m tempted to create everything using the Visual Format Language.

Debugging

One final related point: If you’re doing Auto Layout in code, you need better debugging tools than are currently available. iOS does not provide an instruments template for debugging NSLayoutConstraints, which is available under OS X. The good news is that it just seems to be the template missing, and you can create your own by dragging the “Cocoa Layout” item from the library to visualize when constraints are added/removed from your interface.

The library item in Instruments to visualize constraints

Related:

For more on Auto Layout: iDeveloper.tv has a course available which covers using Interface Builder and creating constraints in code as well as introducing the debugging tools which are available. All sample code is included. You can see a sample and purchase the course here

About the Author:

Photo of Matt Tancock

Matt Tancock

After spending many years as a teacher and hobby developer Matt has now made his way full time into iOS and OSX development as a researcher and developer for iDeveloper TV.

Twitter: @mtancock
App.net: @mtancock
Website: iDeveloper.tv