Mysteries of Auto Layout, Part 1

Session 218 WWDC 2015

Auto Layout is a powerful constraint-based layout engine that can drive complex and dynamic interfaces on both iOS and OS X. Learn about the new UIStackView, now your first stop for interfaces built with Auto Layout. See how to build self-sizing views using Auto Layout, and gain critical insights into the inner workings of Auto Layout.

[ Applause ]

JASON YAO: Wow, wow.

Good morning, everybody.

Good morning.

My name is Jason Yao.

I am an interface builder engineer.

I am going to be presenting with Kasia, an iOS keyboard engineer.

Welcome to the Mysteries of Auto Layout.

As developers, you want to build bold and beautiful apps that will surprise and delight your customers.

Having a great layout will put your app ahead, and your customers will reward you for it.

Having to target all the different devices and configurations as well as multitasking and localization can be a challenge.

Luckily, you have a tool to help, Auto Layout.

Auto Layout, in its essence, takes a large set of inputs in the form of constraints, transforms them into equations, uses linear algebra to give you a set of frames.

And that will give you the layout that you've specified.

Now, working with Auto Layout, you will find it's powerful and flexible but can seem somewhat mysterious at times.

And that's why we're here today, to discover and unravel the mysteries of Auto Layout.

We have a number of tips and techniques to tell you about, and learning them will save you hours of development time and save you from frustration.

Let's get started.

If you are new to Auto Layout, whether you're new or a veteran, there is something in this talk for you.

You can refer to past WWDC sessions if you need a refresher.

Let's take a look at the outline.

This is a two-part session.

We are covering the morning half today, right now, and the afternoon one is in this very same room later on.

Let's get started with the first mystery, mystery number one, maintainable layouts.

Now, when you are working with Auto Layout, you are going to discover very soon you are going to work with constraints.

Picture developing a relationship between two views.

You can have a label on one side, a bundle on the other, specify how far apart it's going to be, where it's going to go into the superview, and beautifully align them along their baseline.

Now, whether those specifications change for you at runtime or design time, Auto Layout will do its thing.

Picture a more complex example.

This is the App Store with GarageBand showing up as the app.

It has a number of controls inside.

It has a label at the top and some buttons, it's got an icon to one side, a segmented control in between, and then some preview images at the bottom.

We can use Auto Layout to lay this thing out and adapt to different sizes.

And the constraints might look like this.

Now for the maintainability part.

Pretend that you were not the developer who created this layout.

But your boss comes up to you and says, I want a new control right underneath the essentials and above the star rating.

Where do you start?

You are probably going to have to examine the controls in the area, look at the constraints, try to insert your button, break some of them, and then reassemble it, hopefully it all works out.

There is a more maintainable way, as you've guessed, that is Stack View.

New to iOS 9 and made even better than before on the Mac, Stack View allows you to arrange your views linearly.

Stack View has parity across both platforms.

It is built on top of Auto Layout.

It manages the constraints of your subviews for you so you don't have to, and it works well when you add user constraints.

You can have a horizontal or vertical orientation or axis, as well as other customizable properties, such as the alignment.

Here you have a whole bunch of horizontal stack views, and here are examples of top, center, bottom, and baseline alignments.

There are other alignments as well.

As well as vertical stack views.

Here are examples of fill, leading, center, and trailing.

Now, one of the properties I want to draw your attention to is really cool, distribution property, and this one is also new to NSStackView as well as it's on iOS 9.

This allows you to distribute along the axis, and you can do some pretty complex distribution behaviors without having to deal with any constraints.

Here we have examples of fill so that we are filling the stack view.

Fill equally, fill proportionally, which is based on the content size of the subviews, and equal spacing.

And there are other distribution options as well.

So we can build Thank you.

[ Applause ]

We can build this out of stack views, so I am going to give you a demo inside of Interface Builder.

All right.

So I've got Xcode loaded.

With a view controller, and to set up my scene, all I have done is dragged a whole bunch of controls and images out from the Object Library and Media Library.

You can see they are all top-level labels, buttons, and images.

Now we are going to go ahead and put these things into a layout.

So first I am going to select my button and my labels.

Then I am going to draw your attention to this new button on the IB canvas, the Embed in Stack View button.

When you click on it, it's created my stack view and affirmed my alignment and my axis.

[ Applause ]

Now we are going to tune the properties.

You can see in the Property Inspector up here that we have the axis, alignment, distribution, and spacing as some of the options, and you'll notice there's also a plus here.

You can make this an iOS 9 size classable.

We are going to go ahead and adjust the alignment, and for the people who have dealt with constraints before in Auto Layout, you will note that all we need to do now is switch it from trailing to leading.

Not touching any constraints.

Let's go ahead and stack a whole bunch of other views in here.

I am going to go ahead and click on my ratings, stack them to horizontal create a horizontal stack view.

I am going to go ahead and drag that up into my first stack view.

Now I am going to select the icon and the header, click the Stack View button for that, and then finally, the top three controls, and my layout is nearly there.

[ Applause ]

Now let's go ahead and tune some properties.

We have the top-level stack views selected.

I am going to go ahead and first adjust this alignment not to center but to fill, so it's really filled across the entire stack view.

And I am also going to spread it out so that it's a little more it's got a little more spacing.

Let's say about 20 points, maybe 25.

Then we will also add some spacing into the stack view with the labels and the buttons, so I am going to go ahead and click on that and change its spacing, and we will give it about five points.

We also want to add spacing between the icon and the header, and I could go ahead and select that stack view using the document outline.

Or I can hold down Control-Shift on my keyboard, click over the icon, and get all the views underneath my mouse click.

So we will click on the closest stack view to me, the horizontal one, and increase that to about 25 points.

Let's go ahead and run this.

You can see it's got my layout, but we haven't positioned it yet in the superview, and this is where we are going to use constraints.

I am going to go ahead and take the stack view and put it against the top and leading margins.

Then I am going to draw your attention to this other button on the IB canvas that brings up the Pin menu and brings up a pop-up for being able to add your leading and top constraints.

And when I hit the Add button, it's added the constraints for me.

Now, we also want to add to the bottom and the trailing, but there's another trick in Interface Builder that you can do.

You can control-drag between two views.

So I am going to control-drag from the stack view to its superview and select Trailing Space to Container Margin.

That's going to add my constraints.

For those already familiar with the menu, check it out, there are a few new other features in there.

We are going to add another constraint to the bottom, vertical spacing to bottom layout guide.

Now I am going to double-click on my constraints, set their constants so they are flush against the edges, and now when we run it, you can see it fits my superview.

Something isn't quite right yet.

Take a look at that segmented control.

It's a little too stretched.

What is going on there?

In fact, if we rotate this, it's a little too squished.

[ Laughter ]

At the top-level stack view, it's looking at its subviews, and all of them have the same priorities, the same content-hugging priority and content compression-resistance priorities.

We will talk more about that later on in the session, but for what you need to know for now is that we need to tell Stack View which one is going to win.

All I have to do is select the segmented control, go into the sizing inspector, choose the priority section, go ahead and adjust my hugging priority because I want to have the segmented control hug tighter, change it from 250 to 260.

You only need to go a little bit above its default.

Likewise, I wanted to resist compression and not get swished, so I am going to also increase my vertical content compression resistance from 750 to 760.

Now when we run it, it's looking much better.

Now remember - thank you.

Thank you.

[ Applause ]

Remember the original problem?

Our boss wanted us to add a new control.

So here's what you do.

You tell your boss, it's okay.

I've got it.

Then you go back to your desk, open up the storyboard, search for the control in this case we will use a button drag it out from the object library, and target which stack view you want to drop it in.

Then you go grab a coffee.

[ Laughter and Applause ]

I would also like to point out that Stack View handles Hidden for its subviews really nicely.

You can set it programmatically or through Interface Builder.

It's like it collapses or is taken out of the view hierarchy but is still owned by Stack View.

So if I mark Hidden, you can see everything adjusts accordingly.

We think you will find this useful.

[ Applause ]

That is the demo of Stack View.

[ Applause ]

I also wanted to point out that animation is really easy, too.

This is what it might look like.

Use a UIView Animate with Duration block and just go ahead and modify the Hidden property of the subviews, and we specially handle those.

Or you can put other animatable properties in there for adjustment, including properties on the stack view itself.

Try, for instance, adjusting the axis so it's going between horizontal and vertical, and you will see something pretty cool.

[ Applause ]

And of course, this is what it looks like on Cocoa.

Use NSAnimationContext, run animation group.

So what have we seen?

Let's take a look at the API first.

It's simple, familiar, straightforward.

You have your axis or orientation, describing whether the stack view is horizontal or vertical.

We have seen the distribution, alignment, and spacing properties.

And then you have methods for being able to add new things to be stacked.

Add and arrange subviews.

There's also an insert and remove.

I want to draw your attention to the Arrange Subviews property.

This property returns you a subset of all of the views that are owned by the stack view.

It returns you the views that are currently being stacked.

What that implies is that you can have views that are not being stacked by Stack View, such as decorators or overlays, and have a clean view hierarchy, and we think you will find that useful.

All you need to do is call Add Subviews for those other cases.

What have we seen here?

Stack View is easy to build, easy to maintain, we believe you are going to compose a lot of these things, and because Stack View is about layout and therefore it doesn't need to render its own background, we've been able to do some optimizations.

So we have a special Transform Layer class that doesn't render on its own that can make Stack View run fast and even more performant than your regular views.

So it is lightweight.

[ Applause ]

We went from an example with many constraints and a little bit of difficulty maintaining it down to just four and a bunch of stack views, and this reads a lot nicer.

We feel that you can build most of your user interfaces with stack views, so we recommend start with Stack View and use constraints as needed.

And that is Stack View.

[ Applause ]

Now, for the cases where you need more than just Stack View, you are going to have to I would like to invite up my friend Kasia to talk about feeding the layout engine.

[ Applause ]

KASIA WAWER: Hi.

My name's Kasia.

I am on the iOS Keyboards Team, and I am here to talk to you about proper care and feeding of your layout engine.

It's a finicky little critter, but it wants to do right by you.

If you treat it correctly, it will treat you correctly.

As you have seen over of the course of the week, we have these new adaptive environments as well as all of the different iPhone screen sizes we have.

It's critical to plan you layout property to work across all these environments and not spend too much time iterating for every single screen.

So most people, when they are thinking about constraints, think of them sort of like this.

You create some views, you create some constraints in different ways, and you kind of throw them into a black hole.

Something happens.

And a layout pops out the other end.

Hopefully yours, possibly not.

So what I really want to do today is try and clear up some of this mystery here and get it so you are hitting your layout every time.

And we are going to start with changing constraints.

When I talk about changing constraints, I am mostly talking about activating and deactivating constraints.

Those of you who have used Auto Layout before and for a while may remember we originally had the concept of adding and removing constraints to and from views.

Well, don't do that anymore.

Activate and deactivate is much better.

It's a class method on NSLayout constraint for both of them, and there are some really big benefits to using activate and deactivate.

Constraints find their own container.

They are more efficient.

And you don't need to own all the views in your layout in order to use them.

So this all really boils down to just don't use add and remove anymore.

Use activate and deactivate.

So there are a few other things to keep in mind when you are thinking about changing your constraints.

Number one, never deactivate everything in self.view.constraints.

If anybody has tried this, you've probably seen some really odd things happen.

Not all the constraints in that array belong to you, such as the ones the view uses to set itself up, so weird things are going to happen.

Just please don't.

We will see why in a moment.

What you need to do instead is keep references to constraints that you may need to change later, either in an array of constraints or as individual constraints so that you can manage things exactly the way you want to.

So let's take a look at changing constraints.

So I have here an iPad app that I've made with a bunch of planets, and it's been set up for iPad and it also has an iPhone mode, so it should work well with multitasking.

Except that I am not actually removing any constraints, so when I move from my nice vertical compact layout back to my regular layout, I have lost all of my nice curve that I had before.

So the first thing I might be tempted to do to try to rectify this is to remove all of the constraints in the superview.

And when I do that, I am also going to need to reactivate any shared constraints.

But you will see all sorts of exciting things happen here if you try to take this approach.

So here's my regular layout again.

That's nice.

And here it is still nice.

Hmm. That's not good.

And if I move back to the regular layout, well, I didn't actually want to make the planets quite that giant, so this is not really what I want to do.

So how do we do this properly?

I am going to take a moment to grab this code so you don't have to watch me type it all out.

So in your trait collection did change, what you want to do is check and see with each environment whether the other set of constraints that you might need to change are active.

Here I have two arrays with eight constraints each that differentiate between that vertical alignment with the planets.

So if I check and make sure that that's active, remove the ones or deactivate the ones I don't want anymore and activate the new ones, it should look much better.

Regular. Still regular.

Compact. And regular again.

So that's where I actually want it to be.

[ Applause ]

Oh, thank you.

So a cool thing in Auto Layout is that you can actually animate constraint changes as well.

Here I have a double-tap gesture to animate between this regular and compact layout by dropping that activation and deactivation into an animation block along with a call of layout if needed to the superview.

So you'll see if I double-tap, I can move really nicely between the set of views with just a couple lines of code.

And if you want to get fancy, you can keep references to all of those individual constraints and use keyframe animations to really kind of spice things up in your app.

So that's activating and deactivating constraints properly.

So what do we know about changing constraints?

Well, number one, never deactivate self.view.constraints.

We know that very well now.

Keep references to constraints are going to change in the future.

It will make everything work better, and you can do cool things like animation.

And you can also animate changing constraints by just dropping it into a View Animation block, which is pretty cool.

So we are still at the kind of basic part of building our layout, where we still have our views and constraints and are putting them into the layout engine.

But if we give the layout engine more information, we can get a lot better results that work properly in all these different adaptive environments.

So we have kind of positioning for all of our constraints, and now I want to talk about size.

So mystery number three, view sizing.

There are a couple different ways to size your views, and you no longer have to say, I want a view that's 200 points wide, 300 points tall.

Instead, you can use different ways to create your constraints adaptively to, you know, work in all of our various environments we have for you now, and we start with intrinsic content size on that.

Many views have this, such as labels and image views, and it's basically the size that the view would be if it was just right around its content.

And the engine looks at this and tries to solve your layout at this size, and it will actually create the internal size constraints for you.

But it can't guarantee the layout size because of stuff like adaptivity, it needs to be able to stretch and shrink views a little bit.

So around things like this, the user won't see it, but you might have a few extra points of padding here and there.

So you can use this in order to lay out your views in a way that means you don't have to specify that this label is this wide.

It will simply be as wide as its content.

But if you need to define a particular view size, start with constraints.

It's very easy to do things like, this view should be half the width of my superview.

This one should be three-quarters of the height of my superview.

This one should be equal to the view next to it.

You can, however, override that intrinsic content size if you absolutely need to.

There are only a couple reasons you might need to do that.

One is if you can't get the size information from the constraints.

And another might be if you are using custom drawing in your view.

But a lot of times you can still just set up the constraints for that view, and you won't have to do anything with overriding intrinsic content size.

If you do override intrinsic content size, you are responsible for invalidating it in case the slide class changes or the text changes that you've got dynamic text, localization, or anything like that that may cause your view to need to recalculate its internal size.

So let's look at setting up a view with constraints without using any particular point sizes, all in relationships.

Here we have a standard image view.

So what I want this to take up most of my view, so I want the width to be equal to three-quarters of the view that it's in.

That means that every environment it's in, the width will be three-quarters of that view.

So I set that up first.

And then I can take that proportion that I now have from calculating from the superviews with and multiply it by one and a half to get the height.

And this will give me a consistent layout across all devices and all modes in multitasking.

So view sizing is important, and the more you rely on proportions, the more likely you are to have a good layout that will really, you know, be easy for you to put across all these different screens we are giving you.

And one of the things that a lot of people when they think about sizing views think about is self-sizing views, and most particularly self-sizing table view cells.

And these are cells that get their height from their content so that you don't have to have one size of cell all up and down your table view.

You can have them in different sizes depending on what's inside of them.

And you don't actually have to calculate every row height yourself.

The constraints can help you with that.

So self-sizing needs to get its size from your constraints.

Again, this doesn't mean points.

This means proportions and relying on things like intrinsic content size to help you sort of do that.

Width is defined with table view cells already, so you just need to worry about height.

And you can take advantage of proportions to do this.

Here we have a table view cell.

The label should be twice as wide as the image view, and they have a little bit of padding between them.

So when I have a label that's taller because it has more text, the table view cell grows in order to accommodate that.

So let's look at a quick demo of how that's done.

Okay. So here I have my table view cell that I have set up the horizontal constraints for already.

If I were to just build and run it the way it is, it would not be exactly what I was hoping for.

So everything is kind of squished.

My estimated table view height is 60, so it's drawing it there by default.

So what I want to do now is tell the table view cell that if the label grows, it grows with it.

And I do that by putting their top and bottom anchors together.

So then the label is going to go ahead and push against the size of the table view cell and make it taller.

So top space and bottom space, to container margin.

Let's see what we get here.

This is better.

But it's still not quite what I wanted.

Because we have cells like this one where the image is now cut off because the label isn't tall enough.

So to fix this, we can take advantage of the fact that views can stretch beyond their intrinsic content size and tell the label that it should be at least as tall as the image.

And so the label will get some extra padding around it that will allow it to to start at the height of the image and stretch beyond that when it's tall enough.

So you don't see that extra spacing, and the text stays nice and centered.

But the label is still what's defining the height of the table view cell.

And now that looks much better.

All of my cells are properly sized, and I can see everything I wanted to see.

And that's really all that's involved in creating self-sizing table view cells.

Just making sure that everything is fully defined.

[ Applause ]

Thanks. Okay.

So view sizing.

What have we got?

Certain views have an intrinsic content size.

You can use that when you are defining relationships to other views.

Constraints should define your size when possible.

When not, you can override intrinsic content size, but make sure you invalidate intrinsic content size when you do so.

For self-sizing views, you just need to define the size fully in your constraints.

Where are we building the layout?

We have our original information.

We are going to add some sizing constraints.

From the views we just put together, their intrinsic content sizes.

What's next?

How do we help layout engine know what we want?

We give it some priorities.

This is mystery number 5.

If you have been doing Auto Layout for a while, you may have landed in a situation where views aren't landing where you expect them to in regard to their superview.

Maybe on each build and run it's a little bit different, or if you rotate or resize it gets a little bit different.

So that's called ambiguity.

And it can happen for a couple different reasons.

One is because you don't have enough constraints in the direction you are looking for.

So for instance, if I had Saturn here kind of where I wanted it in the middle, in this dotted line, but when I actually ran that app it ended up way off to the left or right, that might mean that I don't have enough horizontal constraints to tell the engine where to put Saturn.

Vertically it seems fine, so that's good.

And the other thing that can cause this is equal nonrequired priorities.

Equal required priorities often calls unsatisfiable constraints if the layout engine can't solve your view that way.

Equal nonrequired priorities means the engine has to make a choice for you.

And it tries really hard to make a good choice, but it doesn't really know what you want.

So you just need to give it a little bit more information to get there.

So how do priorities work?

They go from 1 to 1,000, and we have a couple of constants to help you balance your priorities.

One thousand is layout priority required.

Default high is 750, and default low is 250.

And they look like this in a visual format language, you simply put an @ symbol before the number you wish to use.

In Interface Builder, you can stick it right into a text field here.

And if you are using explicit constraints, it's a property.

And that's where you can actually use these constants or numbers or a combination of the two.

The highest priority, when they are competing, wins.

And we'll look at this in the context of content priorities in a moment.

But an important note.

The system has some priorities that it uses to lay out its views internally.

On iOS, we have system layout size fitting size at 50, and there are several window priorities around 500 490, 500, and 510 that OS X uses.

If you look at the NSLayoutConstraint header, you will see what those numbers are.

If you set those equal to each other, you may end up in these ambiguous situations that you're about to see.

You want to use something that's a little higher or lower than the priorities the system is using.

Content priorities.

These are how a view handles its content.

By default, they are set as Not Required, and you should not set them as Required.

Content needs to be able to move a little bit.

We have dynamic text.

We have localization.

We might be able to have users choosing different images, stuff like that.

It needs to have a little bit of wiggle room.

You can't say it always has to be this size.

You will end up with unsatisfiable constraints eventually.

But equal priorities that are not resolved can cause ambiguity, as I said earlier.

Let's look at an example of this using content-hugging priorities, which is one of the two types of content priorities that we have.

Here we have a text field and button, and the text field is all squished off to the side, and the button is all spread out.

That's because they both have a content-hugging priority at their default, which is 250.

The engine needed to make a choice, and it wasn't sure whether the answer was this or this.

So you can actually tell it what answer it should choose every time instead of getting one or the other depending on your environment.

So if you bring the button's content-hugging priority down to 249, you will get the first layout.

And this is because the engine looks at your constraints and your priorities and says, oh, the text view hugging priority is fairly important, but the button hugging priority is not at all important, so I can go ahead and stretch that away from its content to fill up this horizontal part of your view here.

Meanwhile, if you take the button and you put its content-hugging priority above that of the text field, you will get the other solution because the engine says, hey, now I want to hug this button text really closely, and that means that I can stretch the text field in order to solve your layout.

And that's really all that's required to adjust an ambiguous situation like that.

The other type of content priority is compression resistance.

And this is how much a view resists its content getting squished.

So if you have squished is a technical term, by the way.

Feel free to use it whenever to impress people.

Compression resistance priorities for image views and labels in the horizontal direction default at 750, and that's a very high priority because generally you want to see all of your content.

But what if you localize this app?

And you had these two things that were competing, and you had a language that used a much longer word for "red," such as Polish.

It could get clipped.

This is one of the choices that the engine has to make.

It can either shrink the image view or clip your label.

It doesn't really know what you want it to do, so it makes that choice.

If you wanted the label to always show all of its content and it was okay to shrink that image a little bit, again, all you have to do is set the labels content compression resistance priority slightly higher than that of the image view, and now you can see the whole view.

So as you localize, that's the adjustment that's made in order to make sure that all of your text is visible to your audience.

So those are priorities.

They can help you solve unsatisfiability, which is that thing that causes that horrible log that you see when you build and run and everything is broken.

So they are really helpful, but you want to look out for competing priorities.

If they are competing, you can get ambiguity, as you just saw.

Results are more consistent across screens and windows when you do this.

If you use content priorities well, you can get to the right layout.

Sometimes all that's needed is adjusting hugging or compression resistance a little bit.

Now in building our layout, we have added some priorities for your constraints and your content.

So what else do we need in order to finish solving this layout?

Alignment.

Again, if you have been using Auto Layout, you are familiar with aligning your views.

They need to have some sort of horizontal alignment, so they know how to relate to each other, and some sort of vertical alignment.

I am going to talk specifically here about aligning text.

So first of all, with text views, we have the concept of a baseline, and this is the line right under the bottom of the text.

Text views have a first baseline and a last baseline alignment thing, where you can the first baseline runs right under the first line of text, and the last baseline runs right under the last line of text.

A single-line text view has these two equal to each other.

So it aligns text better than top or bottom in many circumstances and helps with stuff like dynamic text sizing.

It gives you better control over changing views as well if something needs to grow.

For instance, if you have a label next to a button and they are aligned by the bottom, the button's frame in this instance is a little large because it's filling in some extra space.

So if I add a couple of lines of text to it, the button can sort of end up in a nebulous area.

And I might want to center align that, or it might be better to have it look more something like messages and have it sit right at the bottom next to that last line of text.

So if I just align them by last baseline, no matter what that text view does, the button will stay aligned with that last baseline.

And of course, you can also do it for the first baseline if that's the sort of view you desire.

So as you have a growing view, it's staying aligned with the views around it.

The other important part of text alignment is leading and trailing.

This is actually important for all types of views, but its big use is for localization.

If you are in a left-to-right language when you are writing your app and you use left and right constraints for your layout and it gets localized to a language that uses right-to-left, you're going to get some odd results.

It will look something like this.

Everything sort of flips in place, but it no longer reads properly.

I was reading from the image view over through the text, and now I am reading the text from the other direction and it's going over to the image view.

That's not really what I wanted.

If you use the exact same constraints with leading and trailing alignments instead, leading for left and trailing for right, you would end up with the correct layout, where everything actually reads exactly the way you originally designed it when you switch to a language that goes in a different orientation than the one you were starting with.

So use leading and trailing pretty much always.

There might be some circumstances where you still need to use left and right.

I am not familiar with any right now.

I am sure that you guys have a few.

But if you do use left and right at all, be careful when you are mixing and matching that with leading and trailing because, again, when that environment changes, you might end up with unsatisfiable constraints.

Okay. Final piece of our alignment puzzle is alignment rects.

Alignment rects are important because it's what the engine actually calculates.

The engine takes all of your constraints, calculates the alignment rects, and uses them to actually lay out your views.

So what are alignment rects?

They are usually the frame of the view, but not always.

Instead of just being the frame around the view, it includes the critical content of the view, which is what you really want to align.

Here we have a checkbox, for instance, where if you were doing a center x alignment with some other view, you would probably want to align it by the center of the circle and not by the center of the checkbox, the whole check, which would be a little bit too high.

Same thing with a button that has a shadow.

It kind of gets rid of those little extra bits and focuses on the critical part of the content.

It doesn't change when the view transforms, either.

So when you lay out your view and want to emphasize or deemphasize something, it won't mess up the rest of your layout to throw a transform in there.

If you do need to change these, which you should very rarely need to do, we have an override for alignment rect insets you can use.

And that basically means you can hand the engine, say, oh, whatever alignment rect you are calculating, inset it by this much and use that instead.

You will very rarely if ever need to do that in your layout, but it is there if you need it.

To find out what the engine has actually calculated for you, you can draw it on your view using the view debugging option in the Debug menu of Xcode and just selecting Show Alignment Rectangles.

This will draw yellow alignment rectangles on your view.

You can also get it from the debugger using alignment rect for frame on specific views.

We are going to talk about that more in Part 2 when we talk about debugging layouts, so definitely tune in there if you want to learn more about how all this works.

So for alignment, we've learned that text is a little bit different than everything else.

You want to make sure that you are ready for both dynamic text and localization when you are preparing your app, and Auto Layout can really help you with that.

You also have this possibility of overriding alignment rect insets if you have very interesting, specific views that need to sit in a very specific frame.

So where are we in our layout?

Okay. We have now alignment, and if we needed to, we overrode a couple of alignment rect insets.

Now we are ready to let the engine do its work.

So let's throw everything in there.

The layout engine will think about it, calculate your alignment rects, and then that will be used to actually build the layout.

Now you have a very happy layout that's exactly what you wanted for every screen size.

Trust me, this is your layout that you wanted.

Okay?

[ Laughter ]

So let's see.

Let's summarize what you've learned today.

Stack views are a great way to build a maintainable layout that will work well across all of our devices and sizes.

And you can use if you use activate and deactivate properly for your constraints, you can get really dynamic, interesting layouts that require less work than having to design for every single screen.

When you determine specific sizes, use constraints.

Override intrinsic content size only when absolutely necessary.

Use priorities to get those last little adjustments together.

Finally, alignment goes beyond top, bottom, and center, especially when you are looking at text, keep localization and dynamic text in mind.

For more information about all of this, we've got some documentation up.

You can download that planets sample code if you want to play around with animation, and of course, you can go to the forums or, in a pinch, contact our Evangelist.

Tune in this afternoon for Mysteries of Auto Layout Part 2, where you will learn more about the layout cycle in depth and more information about debugging a layout that's not doing what you want it to do.

We have some other related sessions here.

Have a great day.

Thank you.

[ Applause ]

Apple, Inc. AAPL
1 Infinite Loop Cupertino CA 95014 US