Tip:
Highlight text to annotate it
X
[ Music ]
>> Stanford University.
>> Alright.
Well welcome to Lecture number 9 of CS 193p, Fall of 2013/14.
Today I'm going to finish the animation demo that we started
on Monday, and then the lecture's going to be
about auto layout, which is a really cool system for making it
so that your user interface cam adapt to changing conditions.
And then I'll do a brief auto layout demo at the end,
just so you can kind of see it in action.
Seeing is believing, especially with auto layout.
So this demo, where we left off is the blocks would come
down due to gravity and they would collide at the bottom
and they'd kind of run into each other,
and then when a bottom row was full they would all kind
of fly off into outer space.
And I think where we left off too was they would stack up
and they weren't flying off, okay?
And so why weren't they flying off at the end?
Well, part of the reason they weren't flying off was
because they were, those towers of blocks were so tippy,
they were kind of wiggling, they were never coming to rest, okay?
So they were never, the animation was never stopping.
It was always continuing to move them a little bit,
and so we're going to start off our demo
by making those stacks a little more solid, a little less tippy,
by making it so that the blocks can't rotate.
So since they can't rotate, they'll sit on top
of each other much nicer and I'm going to turn gravity back
up to 1.0, I think I had typed in .9 at some point,
just as far as the demo, but let's crank it back up so
that they will sit a little bit so they don't float at all,
you know, so they sit down strongly on top of each other.
Then what I'm going to do is use an attachment behavior
so as the block falls, we can grab onto it, okay?
And then we can kind of swing it around and pick
which stack we want to drop it in and then let it go.
And then the last thing I'm going to do is we're going
to use the action block of that attachment behavior to animate
that and show the attachment, I'm just going
to actually draw a little line to show it.
So it's quite a bit to show there.
I don't think we're going to have time
to do this collision delegate thing, but I'll post the code
for that so you can see what that's all about.
Alright, so, let's get back over to Xcode here
and go back into drop it.
And, okay, so, remember that we moved all of the behavior
of this thing out into its own subclass of UI dynamic behavior,
called drop it behavior.
Right over here, this guy, and so that's
where the gravity and the collision is.
And so what I'm going to do there is I'm going
to add another behavior to that customer behavior,
which lets us control things like whether the blocks rotate.
Okay? We can also control friction, resistance, density,
those kind of things in there.
The kind of behavior that is
that controls those things is called a UI dynamic item
behavior, because it's specifying the behavior
of that item.
Okay? So we'll call that, maybe something
like animation options, or something like that,
you can call them item behaviors, some,
you might call them physical characteristics almost,
but that's, we'll do that.
And let's go down here and lazy instantiate that,
so dynamic behavior in the mission options.
If not animation options,
then mission option equals UI dynamic item behavior
alloc init.
So I'm just allocating this thing and I'm going
to allow rotation, no.
So I'm not going to allow these items to rotate.
Okay? So the blocks will have to stay as they bounce
on each other and collide, they'll have to stay nonrotated.
Alright? And return animation options.
And, again, we can do other things in here
like dot friction equals dot density equals whatever,
but we'll keep it simple.
I obviously want all items to be added also
to this animation options thing and we clearly want
to remove all items, [pause] as well.
And let's finally add our child behavior.
Animation option, so the animation options act
like any other behavior, okay?
They just specify attributes instead of, you know,
applying the forces or whatever, but you can actually think
of them somewhat as applying forces too, it's just, you know,
like forces to keep them from rotating or forces
to make them have higher friction, those kind of things.
Okay. Question?
[Inaudible background question] What a great question.
You mean if, if you had multiple item behaviors
that had different conflicting densities or whatever?
So that's a great question.
There are rules for that if you have, you know,
a tree of behaviors and you had some item behaviors in there.
There are rules for which one wins,
it's kind of the last one wins
and how that's happens is all defined in the documentation
for it, so if you're going to build a tree so complicated
that you have the items in there twice
with two different behaviors and different things, I mean,
that's pretty, I mean, if you're doing that, you really got
to know what you're doing and so you really want
to read the documentation,
that would be considered advanced behavior
to do that, but it can be done.
It is legal.
Okay. So, now we'll have that.
So now when we run this, [pause] we'll get a little less
of the tippy stack thing,
although I didn't change the gravity,
but we'll see what happens here,
but you can see they're definitely not twisting,
they're staying.
They still might bounce slightly to the side if they,
for example, if I clicked too fast they might crash
into each other on the way down,
ones that are in the same column.
So here we go.
So now, they're going
to be flying away a little more reliably.
Let's try going really fast,
see if we can get them to tip a little.
Now I, if I have multiple rows, they should all go together.
Notice also I'm starting to get a lot of blocks
and it's the performance that's starting to get a little jerky.
Okay? And that's something you have to understand
with animation, if you have a lot
of things animated, it's not free.
Okay? Animation is not free.
And if you had an application like this
where you were dropping these blocks and you allowed the user
to drop a lot of them, you might have
to start doing some other things, like, for example,
instead of having the collision boundary,
instead of having all the items collide with each other,
what if you just drew a boundary around the top
that they top ones could collide to.
You see? Then you would keep all those bottom ones from having
to calculate where they're going to go, because you'll notice
that after they get tamped down a little bit, they don't bounce
so much at the bottom anyways, so you could take away
that bounce and put a boundary,
because your boundary is a UI DesiPath,
it can be anything you want.
Okay? So you have to think about that only, you know,
when you start getting to extreme cases there.
Okay everyone.
Cool with that?
Make sense?
Alright, so, the last thing we're going
to do is this attachment behavior.
So this is just attaching that bar, which can be a springy bar
or an iron bar, I'm going to leave mine be an iron bar,
you know, a bar that doesn't collapse and expand.
And, we will use that bar to grab onto one that's coming
down so I can swing it into the right column,
because right now it's just whatever column it comes
down in, that's the column it goes in
and that's a little bit restrictive, it makes it hard
for my game to play very, very competitively.
And so, what we're going to do to do this, we need a couple
of things here, in our view controller.
One is we're going to clearly need an attachment behavior,
so I'm going to create a new UI Attachment behavior.
I'm just going to call it attachment, okay?
And, I'm also going to need to know which view is dropping.
Okay? The view that's currently falling
down because that's the one I'm going to grab on.
Because there's a whole bunch of views in my game, right?
Tons of them, all of them are stacked up there, which one,
when I start grabbing, am I going to grab onto?
It's going to be the dropping view, so I'm going to have
to keep track of the dropping view and, in fact,
that's easy to keep track of, I'll just write
down here every time I drop a new one,
I'm going to say the dropping view equals the drop view.
Okay? So every time a new one comes down,
it's going to become the one that gets grabbed.
So if I have multiple of them coming down at once,
it's the last one that started coming down is going
to be the one that gets grabbed,
if I grab onto it with this attachment.
Okay? So now I have the dropping view.
So, I'm going to do the attachment with a pan gesture.
Okay? So we're going to see another gesture recognizer here,
because I'm going to grab it and then as I move my finger
around on the screen, I'm going
to keep the attachment attached to my finger.
So the block that's being grabbed
onto with the [inaudible], it will kind
of follow my finger around, right?
With the bar behind it.
So, that'll be kind of fun.
So let's do that.
So you'll remember the gestures we set up, right,
from our storyboard, right, here's the storyboard.
I'm going to go over and grab a gesture, it's a pan gesture,
which means follow the finger around, so here's a pan gesture.
Drag this out, I'm just going to drag it on top
of my game view, right on top here.
Here's my tap gesture, here's my pan gesture, so I'm going
to drag it out, I'm going to put it down near
where my tap gesture is.
Here's my tap gesture right here, so I'm going
to put my pan gesture right next to it.
I'm going to call it pan,
I'm probably teaching a bad style here to call these pan
and tap, I call them that so
that when you see them you realize, oh yeah,
that's the pan gesture handler, but again,
this could be something like grab drop,
that might be a better name for this than pan.
Okay?
So, there's our gesture, and [pause],
let's make some more space and actually we don't even need
to see, actually let's go back here.
We don't need to see our [pause] storyboard for this.
Okay? So I've got my pan right here.
So what's going to happen in this pan?
Okay, pan gestures, like pinch gestures,
and continuous gestures like that,
they kind of have a similar sequence of events that goes on,
so I have a little snippet that I do the same thing
for all these kind of gestures, which is they start out,
they begin, then they change as they move
around and then they end.
So what are the three things we're going to do
for our pan gesture when we do our attachment?
Well, the first thing I'm going to do,
actually the first thing I'm going to do is I'm going to find
out where is that pan gesture?
Where did that happen in my game view?
And I'm going to do that with CGPoint,
gesture point equals sender location in view, my game view.
Okay, so now I know where in my game view that happens.
So this is a gesture recognizer, right?
This sender is and this method in fan gesture recognizer,
which tells you the location the pan happened or is happening
if it's moving around, it tells you the new position.
So, the first thing I'm going to do is I'm going
to attach the dropping view,
that thing we just said, to that point.
The gesture point.
Okay? So this is a method we're going to have to write,
so we'll put it down here so that we remember to do it.
Though we might, we might remember better
if we don't put this down here, but,
because it'll keep complaining.
We'll do that.
So I'm going to have this attached to dropping view,
that's going to the guts of doing an attachment thing.
Here, when the pan changes, when it moves to a new spot,
I'm just going to have my attachment behavior anchor
point, okay, anchor point, remember,
the attachment can be either attachment between two items
or between an anchor point in an item.
This is going to be between an anchor point,
that anchor point is going to be following my finger around.
I'm going to set that to be the gesture point, okay?
So that's all I'm going to do when it changes.
And then, when it's done,
I'm going to do remove this attachment, remove behavior,
this attachment from my animator.
So my animator is going to stop doing that animation anymore.
Okay? So that's it.
You can see this is all pretty easy to do, all this stuff.
Even this attach is going to be really straightforward.
So let's look at that attach.
How do we create an attachment behavior
between an anchor point and some item?
And it's pretty simple.
If we have an item that's currently dropping, okay,
hopefully we do, then we're just going
to create a new attachment behavior
with UI attachment behavior alloc, and it's init, it has a,
remember, four different kinds of inits here,
depending on whether you're attaching the points
or between two items.
It also has some ways to attach with an offset
so that the iron bar is not connected to the center
of the thing, maybe it's centered a little offset,
it'll tilt a little bit.
So I'm going to do the one which is init with item attached
to anchor, which is this one I guess, and the item is going
to be that dropping view.
Oops, sorry, attach to item, no I wanted a different one,
I want attach to anchor.
And the anchor is going to be that point, right,
where my tap pan gesture went down.
So that's it, it's as simple as that,
and now I have an attachment between that point
and this dropping view, I'm going to be moving that point
as the gesture moves, and the dropping view is just going
to follow around.
After that attachment happens, by the way, I'm not going
to allow you to do it again, so I'm going
to set the dropping view to nil.
Okay? So in other words, I'm not going to let you grab
onto that thing, move it a little, oops,
grab onto it again, move it again, nope, you get one try,
that's just part of the game play, I only want you
to get one try dropping that thing.
And then I just say, animator, add behavior,
and the instance I do this it's going to start animating that.
Okay? Animating an anchor, a connection
between that point and that, that view.
Okay? So, I think that's all that I have to do.
So let's run and see if this works.
Alright, so we have them dropping down,
I grabbed onto it, you see how, you see my mouse,
you can see how I kind of have a hold of it and it's like a bar,
I can even, whoa, balance it on top?
You see? It's a little hard to see, right?
So maybe we'll draw a line
between the attachment point and the little thing.
Okay? Whew.
Okay? So that's the next thing I'm going to do is I'm going
to draw a line between where I'm panning and the,
and the item that I'm dropping.
So let's do that.
And I'm doing that not as much,
partially to show you how the attachment is working,
but also because I want to show you how to use this action,
this little action block that you can use.
So, how am I going to draw that?
Okay? How am I going to draw this [pause] this line?
Well, what I'm going to do is I'm going to make the game view
of my storyboard here be a UI Bezier Path Drawing view.
Okay? So I'm going to create a new kind
of view, oops, new file.
And it's going to be a UI view, subclass a UI view,
I'm going to call it BezierPath View, okay?
And this is going to be a totally generic,
Bezier path drawing view, so it's public API is,
it is going to have one property, public property,
which is a UI BezierPath, called path.
Alright? That's it s entire public API, and all its going
to do is in its draw erect,
it is going to [pause] say path stroke.
Okay? And the only other thing I'm going
to do is self dot path, and the only other thing I'm going
to do here is in set path, the setter for that thing,
I'm going to do under our path equals path, and I'm going
to say self set needs display.
So anytime someone changes the path, it's going to redraw it.
Okay? Everyone understand what this class does?
I hope, right?
It combines everything you know
about drawing, right, and one thing.
Draw erect, BezierPath stroking, set needs display,
the whole thing, so that's it.
Now, I'm going to go back to my storyboard and I'm going
to have this game view, instead of being a UI view,
I'm going to change its class to BezierPath view.
Okay? So everyone remember what I told you about,
if you have a customer view like this, if it starts out generic,
and you drag it out, right, it starts out generic,
and you can change its class, just like with the controller.
Okay? Now, to match this up in my controller,
I better go up here and say that this is a, where is that thing,
in my game view, is a BezierPath view, so let's do that.
BezierPath view.
Alright. So it's BezierPath view,
so that I can send it BezierPath messages, okay?
Alright, so now my game view can display an arbitrary BezierPath,
so now all I have to do is calculate the BezierPath
between, that the attachment shows, basically,
between the anchor point and the dropping view,
and then every time that attachment view changes,
I have to redraw, I have to reset that path,
recalculate it every time.
Okay, so that's where this action block is going
to come into play.
Alright? So, how are we going to do that?
Let's do it right in here, okay?
When we attach, when we create this attachment right here,
we are going to use the little action block of this guy,
action, to update that thing, so, let's go carrot,
curly brace, curly brace, okay, this is how we specify a block.
So we're going to pass this block of code off
to this attachment, and every time it animates,
it's going to call this block of code, and what are we going
to do in this block of code?
Well, we're going to create a BezierPath.
[Pause] Just using UI BezierPath alloc init.
And this BezierPath needs to have a move to,
so let's have it move to the anchor point of the attachment,
so that's self dot attachment dot anchor point.
And then we're going to path add line to, we need to go
to where the dropping view is.
That's self dot dropping view dot center.
Alright? And now we have that path
so I can just say self dot game view dot path equals path.
Okay? Any questions about this?
Yeah?
[ Inaudible Background Question ]
Yeah, so the question is couldn't I just say right here
anchor point?
Because I'm passing anchor point right here.
And the answer is no, I can't do that,
because I'm changing the anchor point, right?
Every time you move that pan, I'm changing that anchor point.
So, this block of code gets executed every time it happens,
so I can't use this anchor point, which was only passed
in here when I first attached it.
I have to use self dot attachment dot anchor point.
In other words, the anchor,
the anchor points current attachment point.
Right? So that's why I have to keep calling that.
Yeah?
[ Inaudible Background Question ]
Yeah. Excellent question.
So, I'm setting this self dot dropping view to nil
and I'm using self dot dropping view in here.
Isn't that going to break it?
And the answer is absolutely it is.
Okay, I did this intentionally, because I wanted to show you
that the things that are in here get reevaluated every time,
this block gets executed each time animation happens.
So how can I deal with that?
Well, I can just, how
about create a little local variable here called dropping
view equals self dot dropping view,
and then I will use that right here.
Okay? So now I've captured the dropping view, here,
in a local variable, and I'm using it here.
So this is referring to this local variable,
not to self dot dropping view anymore, and the fact
that I set this to nil doesn't matter.
This one's still going to be pointing to that thing.
Okay? So that, I just wanted to kind
of show you how blocks capture the local variables
that are just outside their scope.
Now, we have another problem in here, in fact,
the compiler's warning us about it, you see?
Capturing self strong in this block is likely
to read to a retained cycle.
That's a memory cycle like we were talking about.
And, in fact, it's going to.
Because this action, this block, is inside this attachment,
strongly held by it, which is strongly held by us,
so we have a strong pointer to the block, and if I put self
in here, the block is going to have a strong pointer
to us, and that's no good.
So we're going to do this trick, underbar,
underbar weak [pause] UI, what do we call,
what is the name of this thing?
Drop it view controller, that's ourself.
Weak self equals self.
So now I've created a weak pointer to myself,
and now I can use that here.
Weak self.
Okay? Also down here.
Weak self.
Alright? So if I ever got dropped out of the heap,
and no one had a strong pointer to me,
these weak self pointers would all go to nil,
but that would be fine, because if I'm not around,
then this action doesn't mean anything anyway, right?
I'm the controller.
So, so it's all perfectly fine to do that.
Okay? Any questions about what we did there?
Because that's an important thing to understand, as well.
Alright. One last thing we have to do is when the gesture ends,
the pan gesture ends, and we remove the animator,
we're going to want to say self dot game view dot path
equals nil.
Okay? Because this action, once this thing is removed from here,
this action is not going to execute anymore,
so we're not going to get that last action
that draws nothing, right?
We don't want that line to be left there.
Okay? In fact, here, just to make sure you understand this,
I'll leave this out and we'll see what happens.
[Pause] Okay, so I'm dropping here and now, see,
look, I've got my bar.
Dance this thing around, drop it where I want.
Oh, see the bar didn't go away.
Okay? Because that action never called,
that's because of this line of codes,
so let's put this back, now we'll run.
Okay, now we drop one, we got it, drop another one,
another one, grab onto the side, another one,
try and swing it around.
Okay, if we swing it around and smash it in there,
they'll still collide.
Okay? These are still collision, still happening,
and you can see also that our game has a little bit
of a problem right now, by the way, this not being able
to rotate is why it didn't tip off there.
Okay? Because it kind of got, with being,
some item behavior is keeping it from tipping off, okay?
So, this is, by a bad far, game, because how are we ever going
to line these blocks up here, right?
So the next thing we would want to do,
and this is what I'm not going to do because time here is
in the collisions, okay, when collisions happen,
collisions have a delegate, as well.
And in that delegate, what could you do is every time,
and the collision delegate tells you when a collision starts
and when the collision is ended being processed.
Okay? And in that ending handler, the ending message
that gets sent by the collision to this collision delegate,
in that ending thing, you would then grid the thing up.
Probably look at its linear velocity, if it's moving
to the right, move it
to the right a little more until it lines up.
If it's moving to the left,
move it to the left a little more until it lines up.
See? So, not too many lines of code,
but I want to make sure we cover auto layout today
so we won't do it, but, any questions about what we did
so far or what we did here?
Okay. [Pause] Okay.
Alright, so let's get on to the lecture about auto layout.
Where is my [inaudible], there it is.
So what is auto layout?
So auto layout is a way of setting the frame
of all your views, okay?
And these can be frames of views that you make in code or frames
that you drag out into your storyboard, okay?
Although I'll warn you for your homework,
the frames of the cards that you make in code,
you're probably not going to want to use auto layout
to lay those out, you're going to want to use, like,
that grid class I gave you or some class you write.
Okay? Because the rules for laying them out are kind
of beyond even what auto layout can do.
Okay? So that's just a little hint there.
But all the other views, every other, every single other view,
including the view that contains your cards,
you'll want to use auto layout to decide
where it gets put on screen.
So we're going to decide
where to put these frames using rules instead of using numbers,
instead of saying, putting it 20, 20, 180 wide by 200 high,
we're going to use rules to decide where it goes, okay?
And these rules are really flexible and powerful,
and the rules are mostly about the relationship
between one view to another view
or between a view to its super view.
Okay, now why do we want to specify these frames
as rules instead of as numbers?
Because sometimes the bounding rectangle
that contains all our views is changing.
Either because device rotated, we're on a tall iPhone
versus a short iPhone, we're embedded inside
of a navigation controller or not, we're in a tab view bar
or not, we're on an iPad in some popover controller view
or something like that, there's a lot of reasons
that are bounds would change size,
so we want to build our views so that what's inside
of them adjust automatically.
Okay? And that's part of, a big part of your assignment,
although, your views want to, in terms of your card view,
want to adjust automatically anyway, because you're adding
and removing cards from them and so they have to adjust anyway,
so you kind of get, probably get that for free, but all the rest
of your views, the one that says redeal and score and all that,
you're going to want to use auto layout to make those fit
in the right place when you rotate the phone.
Now, there, these rules, by the way, we call them constraints,
layout constraints, so that, when I use the constraints,
that's what I'm talking about.
The rules for how to set the frames of all these views.
There's a really powerful API in iOS for this, in other word,
a program interface with object and its layout constrained
and all these mechanisms, but really, almost all of what we do
with auto layout, we do in Xcode, visually,
we don't usually go to the code.
If you're going to the code,
you're doing some pretty advanced layout, okay?
I'm sure it's possible, actually with the code,
you could lay your cards out using auto layout,
but Xcode, probably not.
Okay? So since it's all Xcode and it's all graphically,
I'm going to do this entire lecture about auto layout
with screen shots, okay?
And we'll just kind of walk through it, I'm actually going
to skip these first few here
because I'll show you that in the demo.
So what I'm going to do it I'm going to start with a view,
controller's view, right here, with a couple of things in it.
Thing one and thing two, with apologies to Dr. Seuss,
things one and thing two, they can be any kind of view,
they're UI labels in this case, but they could be buttons,
they could be custom views, whatever, they're just thing one
and thing two, and we want thing one and thing two to be
in the right place when this bounds changes.
Okay? So what happens right now, if we go and try and show this
in landscape, well, I could run this and then flip the simulator
to landscape to see, but it's actually possible
to take your view controller seen,
and flip it to landscape in Xcode, okay?
Now there are two ways to do,
one is Xcode actually has a previewer,
a previewer that will preview what your UI's going to look
like on different rotations, different iPhones,
even between iOS 7 and iOS 6,
if you're writing an app that's compatible for both.
But another way to do it is just to inspect your controller,
so here I've selected my controller, right,
it's got a blue boundary around it and I've selected it,
and I went to the attributes inspector, you see?
Upper right there.
And I'm inspecting it.
And if you look at the inspector for controller,
the top five things there are called simulated metrics.
And this is a way to simulate your user interface
in different orientations or sizes or with tab bars or not,
so that you kind of make sure your UI is working
with auto layout, so we're going to go
and switch the orientation, alright, so I'm picking
on this thing orientation, and I'm switching it to landscape.
And when I do that, my scene changes
to landscape and I lost thing two.
Okay? What happened to thing two?
Well, thing two is actually there, I left it there,
it's kind of grayed out, you see it?
But it's not on screen because unfortunately
in landscape it doesn't go down far enough to reach thing two.
Okay? So I'm going to switch back.
By the way, you notice that the orientation there,
there's portrait landscape and there's also inferred.
Okay, for all of these things where you change the bounds
of your scene, inferred means inferred from what's going
on in your storyboard.
So if it's this is the thing that makes a bar come
across the top if this scene is in a navigation controller,
or a bar across the bottom
if this scene is a tab bar controller, okay?
Portrait is the default inferred orientation,
so if you pick inferred, just like you pick inferred
for the other things, it will infer that you mean portrait.
So whether you say portrait landscape, portrait
or inferred are the same for orientation.
Landscape means landscape.
So let's go back to inferred, or to portrait.
We get thing two back.
Whew, okay, thing two didn't go anywhere, it was there before,
it just wasn't on screen.
So, I want to put thing one and thing two in better places.
They're kind of in random places, I want to put them
in places where I can have a rule that says where they are,
and then what I'm going to do is I'm going to put thing one
in the upper left corner and I'm going to put thing two
in the lower right corner, and I always want thing one
and thing two to stay in those corners,
no matter where those corners move.
Okay? If those corners move up in the landscape or down
because it's an iPhone, the tall iPhone, like an iPhone 5, or up,
or whatever, I want those things to stick to their corners,
so the rules I want is stick in the corners, okay,
I'm going to show you three ways to set rules, over the course
of this lecture, three different ways.
The first way, you have already been doing.
Unwittingly, well, not really unwittingly
because I've been telling you to do it,
which is to use those blue guidelines, okay?
When you drag things around and you let the blue guidelines snap
to certain locations,
you're basically telling Xcode what you want.
So when I drag thing one up into this upper left-hand corner
and these two blue lines appear, it's really telling Xcode, yeah,
I want it to be stuck to this line and stuck to this line,
in other words, upper left there.
And same thing when I do that for thing two.
Okay? I'm kind of telling Xcode.
But if I drag these two things then, right, and then I switch
over to landscape again, I still don't get thing two.
Why not? Okay, I did the blue lines, how come it doesn't work?
And the answer is, all the blue lines are is telling Xcode what
you intend.
You still have to ask Xcode, make those rules for me,
make those constraints.
Okay? So let's go back to, to the portrait orientation,
and the way you do that, is the little buttons at the bottom,
you see these buttons at the bottom, those,
here I'll click on one.
Those all have to do with auto layout, okay?
And how you're going to layout the view.
And this one, that looked kind of like a Thai fighter,
a Star Wars Thai fighter there, that one is kind
of for resetting, clearing constraints for the entire view,
okay, or for a specific view or number of views
that you have selected.
So the bottom part of this menu is the entire view,
the top part is the same things,
but for specific clicked on views, okay?
So, we'll go through a few of these things,
but a really cool one is reset to suggested constraints, okay?
Suggested constraints means Xcode is going to suggest
to you the best constraints, the best rules, and it's only going
to be very good at that if you use the blue guidelines.
Because if you don't use the blue guidelines,
it doesn't really know what to suggest.
It'll suggest something, but it's not going
to be good as we'll see.
But in this case, since both thing one
and thing two clearly have blue guidelines to say
where they want to be, when we do reset
to suggested constraints, it's going to work.
Now, nothing appears to happen, right?
I did reset suggest content and nothing happened.
But something did happen, and we can see that by clicking
on thing one and going over to the size inspector.
Okay, so in the inspector there, I've switched over to size,
that thing looks kind of like a ruler, and size inspector has,
you know, where the current frame is and all that,
but at the bottom, do you see where it says constraints?
And I have two constraints.
My leading space, okay,
the reason that says leading space instead of left space is
because some languages, leading is on the right.
Okay? So Hebrew, a language like that, it's on the right
so you might want your entire user interface oriented towards
coming from the right, okay, instead of coming from the left,
because all your text is going to be going that way,
so you might want all your user interface to flow from that way.
So anyway, so leading means whichever leading you're talking
about, and I want the leading space to be tied
to my super-view, the edge of my super view,
by some fixed amount, and that fixed amount is default.
Default. Okay?
It's not a magic number, its default, it's by the system,
the system decides what that default amount is.
And then you can see my top space is also tied
to my super-view's top edge with the default space.
So those two constraints determine exactly
where thing one's going to be.
Now what about thing one's size.
Okay? Is thing one always going
to be exactly the width it is right now?
No. Thing one, like all labels and buttons,
it has what's called an intrinsic size.
Okay? That's the size that its text demands that it be.
And that could change.
If you change the text in thing one, it needs to be wider
or it could be shorter if you change it to something shorter.
And so, it will change its size as you change its text.
Okay? Because you haven't put a constraint on its size.
If you put a constraint on its size, it would then be stuck
to that size and that is bad.
We do not put size constraints, generally,
on intrinsically sizable items like labels and buttons,
and I'm going to show you, hopefully, if we have time
in the demo, why that's bad, okay?
So anyway, thing one only has those two constraints,
but those two constraints completely determine thing one's
location no matter what the super-view does.
Same thing with thing two, bobbing space
and the trailing space.
Okay? So now let's go look in landscape.
I'm going to switch over to landscape and see what happens.
And you can see, thing two sticks to that corner,
kind of exactly what we want.
Alright? And that's because thing two's position is totally
determined by those rules now, okay?
Okay, so let's go back to portrait.
So, I'm going to put a bad thing in there, okay?
So this bad thing is going to show bad things that can happen,
and I tried to put bad thing in the middle,
but I didn't use the blue guidelines.
That's actually difficult to do, but I did.
Okay, I put a bad thing in.
Also, you know, this bad thing size, it's too big for itself,
it really doesn't want to be that big,
it could be a lot smaller if it was just an intrinsic size.
So, I just dragged it out and moved the sizing handles.
It has no constraints, because I just dragged it out, okay?
See how its size inspector there says no constraints, right?
You have no constraints.
So, what happens if I try to ask Xcode,
please give me some suggested constraints for bad thing.
Remember, I didn't use the blue guidelines
when I dragged bad thing out.
And notice, also, I'm using the top half of that menu
which is just, just for bad thing.
Okay? I'm not resetting thing one and thing two,
although I could reset thing one and thing two all day long,
because there's always going to reset to the proper constraints
because I'm using the suggested constraints for them.
But anyway, so I'm just going
to reset bad things constraints and, boom!
Xcode gives it the old college try, but it's hard, okay?
And, in fact, look
at the constraints it came up with there.
Height equals 62, leading space equals 89, trailing space 68,
in other words, these are all magic numbers.
Okay? This is horrible, these are terrible constraints.
Constraints with magic numbers are almost always bad.
There's a few cases where they're okay,
but it's almost always bad, and, in fact, if I go and try
to switch to landscape,
all of those number stay exactly the same, okay?
It stays 198 pixels from the top, and whatever it was
from the left, it's totally not what I want.
Okay? I tried to put bad thing in the middle.
I want it to stay in the middle, that's not even close
to being in the middle.
So suggested constraints aren't going to work
if you don't use the big, blue guidelines
because it's not really sure what you want.
Okay? So, so let's get rid of these constraints.
I'm going to go back to that same menu
and pick a different item, which is clear constraints,
and that clears all the constraints,
and goes back to this thing.
Notice, by the way, all the constraints draw,
you see the blue bars?
See them? Every single constraint is drawn.
And not only does it draw those constraints, you can click
on them, and edit them.
A lot of the constraints have attributes, which I'm not going
to have time to talk about today, unfortunately,
but those constraints are first-class objects inside
of your, your storyboard.
Alright. So we're going to clear those out of there.
And let's put in some constraints in a different way.
So this is way number two to add constraints.
And way number one was use blue guidelines and say suggested.
That's way number one to put constraints on.
Number two is you can use some
of these other buttons at the bottom.
Like this particular button here for aligning things.
So if you look in this, there's a lot of choices of how
to align things, if I selected multiple views,
then all of those things at the top, like leading edges,
trailing edges, top edges, I'd be able to pick those
and I could line up the leading edges or trailing edges
or whatever, of views, make them line up.
Okay? It's just alignment things, just like if you're
in some drawing program or something.
I'm going to pick the bottom two, which lines this thing
up with the horizontal center in the super-view.
So it's going to be centered in my super-view, both horizontally
and vertically, so I'm going to add two constraints here,
one for horizontal, one for vertical.
And I can also specify an offset from the center,
that's what that zero is right there that's selected,
but I'm going to have the exact in the center,
so I'm going to say zero.
And there's also update frames, you see the update frames
at the bottom there right
above where it says add two constraints.
That popup, you can go in there and say,
and when you add these constraints, move my view
to fit those constraints, but I'm not going to set
that because I want to show you what happens
if you don't do that, okay?
So let's add these two constraints, horizontal
and vertical centering.
Okay. There they are.
You see them, align center X to super-view, align center Y
to super-view, awesome.
You can see them, they're there.
Notice that they're yellow.
Okay, yellow is like a warning, okay?
Yellow is not good.
Blue is good, yellow not so good, red is really bad.
Okay? Sometimes your constraints will be red,
that's if they conflict.
Like you have two constraints sitting, doing opposite things.
And we'll talk about how we resolve all this.
>> So it's yellow.
Also, if you look really closely,
you see there's a dashed box, kind of right, it goes right
through the word bad over to the thing, you see it right there,
dashed box inside of the bigger box?
That dashed box, I don't know how well you can see that there,
yeah you can see it, that dashed box is
where you constraints say this thing should be.
Okay? In other words, if you just looked at your constraints,
where should bad thing be?
Well it should be in that little dashed box,
but since we didn't click that thing at the bottom there
that said update my frame
to where my constraints are it didn't do it.
So bad thing is still where it was,
and that's why these are yellow.
Okay? How can I know why my constraints are yellow?
Well one place is that little triangle in the upper corner,
the normal triangle where you would look at any other warning
in your app, and you can see this as the frame
for bad thing will be different at run time.
That's because at run time the constraints are going
to be applied and it's going to be moved
into that little dashed box.
Okay? Another place you can see these warnings,
if you're constraints are yellow is in the document outline.
Now we have not had a chance to talk about the document outline
in this class, but there's not really a lot to say about except
for that it's really great and what is it?
It's every single object in your storyboard
that matters in an outline form.
Okay? So that's all your views, all your gestures,
all your constraints, things like layout guides,
which we're really not getting a chance to talk about,
but has to do with auto layout system, as well.
Those are all listed in this outline, and what's really cool,
is you can click on them to select.
Because sometimes your view's very crowded and it's hard
to click on the thing you want even using the control shift
trick that I showed you,
and also you can control drag from them.
Okay? You can control drag from a gesture,
you control drag from a view.
It's a really great place to control drag things from, okay?
That's pro-tip number one.
Drag, control drag from document outline.
The document online, also, will show you all the problems
with your auto layout and you see the tiny, little,
yellow circle up there where it says view controller scene
at the top of the document outline and then there's
that little yellow circle, I'm going to click on that circle,
and it's going to show me all the auto layout problems
in this controller, in this scene.
And you can see the bad thing, it expects a certain frame
and the actual frame is different.
And you see the little triangle there,
if I click on that triangle, it will offer me to,
offer to solve the problem for me.
Okay? Now, how can I solve the problem?
Well there's a number of ways it could solve the problem.
It could change the frame of bad thing
to be what the constraints say, that's what update frame is.
It could update the constraints instead of being the vertical
and horizontal center that I just sent it to,
it could set them back to being something that would make,
you know, the bad things frame work, or it could try to set it
to the suggested constraints,
which we already know don't work.
So we definitely want update frame in this case.
We know we like our constraints,
that's the horizontal, vertical centering.
So we're going to pick that.
So I'm going to leave update frame suggested and click
where it says fix misplacement, and watch what's going
to happen to bad thing.
It moved. Okay, now, everything is no longer yellow,
bad things frame has been set
to what the constraints demand of it.
Okay? And I just hit back to go back to, in the document online.
So now let's go look in landscape
and see what happens to bad thing.
It stays centered.
Okay? Bad thing properly stays centered,
because the only rules it has, is for it to be in the center.
Okay? Alright, so back here.
Okay. You can also click on, I told you,
you could click on these constraints.
So here I clicked on the vertical constraint there,
you can see, I just clicked on it,
and you see how it's kind of highlighted.
Also notice that the attribute inspector started being an
inspector that's inspecting the center X alignment constraint.
Okay? And there's a lot
of things you can set about constraints.
Notice there's a priority there,
because you might have two constraints
in a complicated layout, only complicated ones,
you might have conflicting constraints.
You want something to be underneath something else,
but you want it to try and be in the middle of the screen,
but if the screen gets really small, then you want it
to just move down out of the way of the thing on top,
those kind of conflicting constraints you can set
priorities, and say which is more important?
Is it more important to be in the middle
or is it more important to be underneath this other view?
You see what I'm saying?
So you can set your priorities between zero and a thousand,
so you, up to thousand items could have varying priorities
and generally you're going to only use two
or three different priorities in your application, but, anyway,
the other thing you can do
when you have this selected is hit delete.
And that deletes that constraint.
And now you can see the bad thing only has this center
Y constraint.
So it no longer specifies where it is horizontally,
and that is really bad and now if you look
at the document outline, I not only have a little dot
up there, but its red.
Okay? And if I had a constraint that was bad here,
the problem is I have a lack of constraint,
I don't have enough constraints to specify
where bad thing is horizontally, but if I had two
that conflicted, they would be red.
Okay?
The constraint, the lines on screen would be red
and I would have this little red circle.
So let's click on that red circle in the document outline
and here it's saying missing constraints, okay,
bad thing needs constraints for X position,
it's saying, which it does.
Because how else is it going to know where to put X, bad thing,
there's nothing that says where to put it because I took
that constraint that was telling it to be in the middle away.
So let's click on that red thing, and when we do,
it's going to offer to fix that.
And it says let me try and add a missing constraint,
and it's going to do the best it can to add a constraint
or a number of constraints to make it so that
at least there's not a missing constraint.
This might not be the constraint you want, but, you know,
it's probably going to be mostly suggested constraints,
but it's going to be some kind of constraint so that there,
so the position of this thing, and its size,
are completely specified.
So, in this case, since we already blue guidelined this
thing to the midline, and we know it's exactly in the middle,
it, when we hit add missing constraints,
it's going to put that thing back.
Okay? Now it's not putting it back
because it knows I deleted it, it's just thinking ah,
that's the best constraint that goes here.
Because it knows this thing is dead center, so it's like, hmm,
dead center thing, I'm probably going to do that.
So it's really smart about what missing constraints it will put
in there.
Mostly it's going to use suggested constraints,
but it's even smarter than just the suggested system.
Okay? So now we have no auto layout issues,
we're back to having bad thing in a good spot.
Now what if I decided I don't want bad thing in the middle,
I want bad thing to be stacked on top
of thing two all the time?
So I just pick up bad thing and drag it down,
I'll use the blue guidelines, or not, but I'm using the,
I'm just going to drag it down there and I drop it.
And what happens?
Well, I get the yellow guidelines again,
because bad thing, once again, is misplaced.
That's because when you drag things to new positions,
it does not change the constraints.
That's important to understand.
When you drag things somewhere new,
the constraints stay the same.
So bad things constraints are still align center X
and align Y, you see?
See them right there?
And that's no good.
So, what can we do about that?
Well, we probably want to delete these constraints,
because they no longer apply, and I showed you how
to delete them by doing clear constraints, and I told you how
to delete them by clicking on them and hit delete.
Here's another way to delete them, you see the little cog,
right there, where it says align center Y and align center X,
there's a little cog, if you click
on that there's a little menu, you can edit it,
which is exactly the same as attributes inspector
on it, or you can delete it.
So I'll delete that one and I'll delete that one.
So now I got rid of those constraints, bad things back
to having no constraints.
I just did that because I wanted to show
that there's multiple ways to get at this thing.
You can also delete them by selecting them
in the document outline and hitting delete.
Okay? So now I have bad thing, but where it is there,
it's not tied to thing two.
If I were to go landscape right now, it would not stick
with thing two because there's no constraint
that ties it to thing two.
Okay? So, let's put a constraint.
Here's way number three, okay,
do you remember what ways number one are?
Number one is blue guideline suggested constraint,
that's way number one, alright?
Everybody got that?
Number two is to use the little menu things at the bottom.
Click, bring up the little thing, type in,
click horizontal, whatever, click the things that you want.
Way number three is to control drag, control drag,
just like you're making an outlet, between two items
that you want to have some sort of constrained relationship.
So I'm going to control drag from bad thing to thing two.
Okay? And when I do, I get a little black box just
like if I was making an outlet,
but this time it's saying what do you want to tie
between these two items?
What do you want to be fixed between these two?
So, you can actually select multiple of these using shift,
that's what it says at the bottom there,
hold shift to select multiple.
So I'm going to pick the vertical spacing,
I want bad thing to always be a fixed vertical space
above thing two, and I'm also going to pick right edge, okay?
And this is saying left and right, but it's really trailing
and leading, it just, right now it knows which is your left
and right so it's saying right to be nice to you.
So I'm going to pick both vertical spacing
and the right edges, okay?
When I do that, you can see I get two constraints.
You can see them on screen, two little blue lines in the IB,
between bad thing and thing two, that is lining
up the right edges and fixing the space
between them to the default space.
Okay, that's because I used the blue guidelines.
If I hadn't used the blue guidelines
and had put bad thing, you know, 40 pixels above,
then it would have fixed it to 40 pixels,
but we would have seen in the constraints 40,
and we said a magic number is in constraints, we better fix that.
Okay? Which you could do by editing the constraint and just,
there's a button actually
that says put it, make it the default.
Alright?
So now I have these two things tied in that way, again,
this is totally enough to specify all
of their positions exactly, because thing two is tied
to the corner and bad thing is tied to the right edge
and just above thing two.
So, if we go to landscape again, bad thing will always stay
that distance and always to the right edge of thing two.
Okay? So that's way number three to attach things is
to control drag between them and you control drag between items,
between views, you can also control drag from a view
to its super-view, that's what I'm doing here.
Bad thing to its super-view and you'll get a different set
of options, like horizontal and vertical container.
Or you could also control drag to yourself.
Okay? Why would you ever control drag to yourself?
I have a bad thing, why would I control drag bad thing
to itself?
Well then I'll get the option to do things
like fix bad things width, okay?
Which I told you was bad anytime you have a button or a label
of anything that has, you know, an intrinsic size like that.
It'll also, if there's some nearby thing it could do,
like fix the trailing space to its container,
it could do that for you too, but you can control drag
to yourself too, which sounds crazy,
but you'll get used to, to doing that.
So control drag is way number three to set up constraints.
Okay? So, there is a lot to this system.
I've just tried to kind of show you
where to look for everything.
How to click on things, where to inspect them,
where to see the constraints,
how to go on the document outline to resolve problems,
whether they'd be red or yellow, it would take me many lectures
to cover all the different kinds of constraints
that you can set up, and, you know, for example,
do you see on the, in the inspector there
where it says content hugging priority,
and content compression resistance priority?
That hugging priority,
that's not because these views love each other,
but sometimes they do, but mostly the hugging priority is
because you have sometimes views
that are sharing some horizontal or vertical space.
And when they share, and that space gets removed from them,
or gets taken away, or they get more space added to them,
they need to know which of those views wants
to keep its size the most and which of them wants
to get extra, and which is willing to be compressed
and which is not willing to get compressed,
thus you have compression resistance priority
and content hugging priority.
Okay? So, that's as much as I'm going to say about this,
you've got to read up on those if you're going to do that.
You don't need, you're not going to be building UI's,
I don't think, like that in your homework, if you are,
more power to you to go look up content hugging
and content compression resistances.
Okay? The last thing there you see is intrinsic size.
Again, a bunch of iOS things have an intrinsic size,
like labels and buttons, but you could actually have your own
custom views, again, not for your homework,
you could have your own custom views
that have their own intrinsic size, they just have
to implement a little API that reports their intrinsic size,
and that little popup there lets you tell Xcode how
to handle that, because it doesn't really know how
to handle that [inaudible] system objects,
like labels and buttons.
Okay? So the demo I'm going to do is I'm going
to take attributor, which I, hopefully,
you still remember attributor
from three lectures ago, or whatever it was.
And we're going to make attributor
so it auto-rotates and looks good.
Attributor is the thing that had the text and we could outline it
and pick the colors, remember that?
So we're going to make that do that.
We used the guidelines when we built attributor, so it's going
to be really easy to make this work.
Okay? But I just want to show you what it all looks like,
to make it go.
And I'll do this slide because we'll finish with the demo.
On Friday, I'm still hoping
to get this university developer thing going, again,
I'm not going to require any of you to get the thing working
on your device until I can get you
into this program, so, no worries there.
And those of you who are doing the 99 dollar program,
you're all good to go, hopefully it's all just working for you.
Your homework, as you know, is due on Monday,
and next week we're going to do a scroll view and table view,
actually we probably won't do collection view,
the more I think about, and the other thing we're going
to do next week is iPad.
Because everything we've done so far is iPhone,
it's time to start doing some iPad.
Okay? So let's go back to attributor.
So I'm going to get Xcode up here and let's close drop it.
Stop that task, [inaudible], and so alright, let's go back here,
and I'm just going to bring up attributor, as,
as we last left it here.
Remember this is what attributor's user interface
looks like here, we don't need to see the code at all today,
because we're going to do all of this auto layout stuff in Xcode.
And let's see what attributor does right now.
So let's run attributor, just as we left it off.
And here it is, here's attributor,
remember we can do this kind of stuff, pick these things,
and if we rotate, and everyone saw on [inaudible],
the way we rotate is we hold down the command key,
it's basically this right here.
Command, arrow.
Okay? So I'm going to do command arrow.
That looks pretty bad.
Okay?
In fact, that's horrible.
Because we've lost all of our control with no outline,
no colors, we can't really do anything here.
Stats still looks okay, but it's kind of cutoff,
that's not so good, dot, dot, dot, so,
really this whole UI did not react well, and so, let's try
and fix it so that it stops doing that, and this is going
to be in some ways almost too easy,
because we dragged all these things out using the guidelines,
so I'm just going to go down here, to the Thai fighter,
and I'm going to say reset to suggested constraints.
And pretty much that's going to do it.
So let's just rerun.
Okay, we could make a quick look at some
of these constraints just to see what's it doing, but like this,
let's get this out of the way in here.
So, you can see that this thing is tied to the super-view
on the left, it's lined up with the buttons.
It makes a little space in between the buttons,
a little space at the top,
so it's pretty much doing what we want.
Let's see what happens when we rotate now.
So we got this, it's still all working, nothing has broken
because of our, putting those constraints in,
and so we'll rotate, ooh, that looks pretty good!
I can still, for example, set my outline, I can set colors,
that's great, stats, ooh, much better.
However, this is not so good.
Okay? I like purple, but not that much [laughter].
Okay? So we've got to make these things all the same size,
we want these four buttons to be the same size, okay?
Nothing that we did when we dragged it in, evidently,
was enough to let Xcode know that.
However, so simple to make that happen, I'm just going
to select these four buttons, I'm going to go down here
to this little [pause] constraint adder right here,
and I'm going to just click this button
that says I want these four buttons to have equal widths.
In other words, I'm adding the constraint
that their widths be the same.
Okay? So, I just, when I hit add three constraints,
it's going to add one constraint to each of them, probably,
each of these first three, saying,
be the same as the next one over.
We'll do that.
You can even see the, see,
here's what they look like, equals.
See? So let's go and run and see if that fixed it.
And it did.
Okay? So, whichever way, by the way,
why does it not rotate here?
Because this is the upside down, portrait upside down,
and in our [pause] project settings,
we said we don't support portrait upside down,
so that's why it just does nothing.
When you go to portrait upside down, it does nothing.
But when we stay with portrait right-side up,
or between either the two of the landscapes,
it seems to be doing exactly what we want here in this view.
And, the only problem is, if we look at our console,
we're getting all kinds of errors here.
Okay? This doesn't look too good.
Okay? And what is this primary error we're getting.
Unable to simultaneously satisfy constraints.
Okay? So, this looked all good over here, there was no,
I don't see anything, there's no yellow things.
If I bring up my document outline,
there's nothing yellow here.
My auto layout constraints are good!
Well, actually they're not.
Okay? Because it's unable
to satisfy the constraints at run time.
Okay? Well why is that happening?
Well, it'd actually give you a lot of help
as to why that's happening, let me make this wider.
Here, and it gives you even kind of ASCII text,
kind of descriptions of the layouts.
You see? How everything's laid out?
But I can probably guess already
that since I just introduced this error, it has something
to do with what I just did.
Okay? Which is to make those widths be the same.
So, let's take a look at the constraints of these buttons
and see if we can see something obvious.
Okay? Anyone see anything obvious in here?
That doesn't look very good?
[Pause] Speak up.
[Inaudible background comment] Yeah,
the width equals 64 here is hardcoded, okay,
that's a magic number, that's bad.
And, in fact, we know that when we go to landscape,
the width's not going to be 64 anyway!
Right? They all get a little wider in landscape.
So this is the problem.
It's trying to make those buttons all the same width,
but you're trying to keep them all 64,
or at least to keep this one and this one and this one 64,
this one seems to not have that 64, which is nice.
So this is easy to fix.
I'm just going to delete these width equals 64's,
it's not the height equals 64.
So let's delete the width equals 64,
let's delete this width equals 64, and we'll delete this one.
Okay? So, this height, nothing turned yellow, okay?
Nothing was like missing constraints, okay,
it's all completely still specified, and now if we run.
Okay, and we rotate back and forth.
Still working, still making the buttons wider,
and we're not getting anything in our console here.
So sometimes you'll get the constraints,
you won't have any problems in Xcode,
but you still might have some conflicts,
so you should be looking at your console
to see if there's conflicts.
Question? [Inaudible background question] Okay, so the question,
why did I keep the height equals 64 magic number,
and that's a super good question.
Now, it's okay that I have a magic number here.
And why is that okay here?
That's because there's no text in that button.
It's almost like an image, right?
So, what size would it be otherwise?
There's nothing, if you look from top to bottom in this view,
there's nothing that would specify what size
because this is not a fixed width, or height rather,
this is a fixed height and so is this and this,
but then how much space goes to this and how much goes to this?
By fixing this one at 64, this one gets the rest.
Now, I actually could do this another way.
If I kind of wanted, you know, the text view to have most
of the space and this, some of it, and I want it
to be a minimum layer, minimum size,
I could actually set the size here to be greater than or equal
to some particular size,
and I could use the content hugging priority
and compression priority between these two to make sure
that whichever I wanted to get the extra space,
when it got taller, like this, okay?
I could make that be defined, but by fixing this one,
I'm guaranteeing this one gets all the extra space.
So when you have an image,
I said that sometimes a magic number's okay, usually it's
when you have an image, some artwork
that somebody has drawn has a size to it that that's it size.
And here, these squares, I want them to be this size, so,
like I said, I'm glad you brought that up
because that's a good question.
Okay, the other thing I'm going to do here is play
around with this, so this is working fine,
nothing to change here.
What about this guy over here?
Well, this one's pretty bad.
I kind of dragged these in here without using the, the lines
or something, so they're kind of in random spots.
So here's a good chance to show you how to put these things
in their place, not using suggested constraints.
Okay? In other words, actually specifying.
So I'll show you both ways to do it.
The both non-suggested constraints.
So let's put outline text in this corner down here, and,
or we'll color it, put color down there, whichever,
and then we'll have the other one stacked on top of it.
So I eventually want it to look like this and this,
but I'm not going to use the guidelines, okay?
Because I want to show you a different way to do it.
So, here I have colorful characters.
So it has no constraints, currently,
because when I said reset suggest constraints,
I was doing that for this guy only, right?
When you go here to the Thai fighter,
it says in attributor view controller,
it doesn't say stats view controller, so it only did it
in that one, and I didn't reset it here,
so these things have no constraints.
So let's set this one to be in this lower left-hand corner
without using the guidelines.
So I'm going to do that with this guy.
Okay? So this little button right here, it lets you specify,
this is where we did equal widths,
but here I only have one thing selected,
so I can't even pick equal widths,
I'd have to pick two things for that, but up here at the top,
you'll notice, you can specify
that this thing is tied to views around it.
Either its super-view or its other views.
Okay? And also, I can pick the standard value here.
So I'm using the default value, okay?
Which you generally want to do, you don't want
to have a magic number, like 100 and 71, in here,
but I'm not picking these high beams,
so those are not going to be affected.
And do you see, it wants to add those two constraints,
that's this one and this one.
I'm also going to show you this, update frames.
You can update the frames, in other words, move the view
as it currently is showing the scene, either all the frames
in the entire container, or just the frames
that got new constraints.
Usually you're going to pick this one,
items with new constraints.
So I'm going to hit this, and watch what's going to happen,
that colorful thing, it's going to jump
to lower left-hand corner,
standard distance away, automatically.
Okay? So that's another way to set the constraints,
see it put standard distances here,
it's got these standard constraints,
and how about this guy?
We want this guy to be lined up on top of this one.
We could do that, also, with this, okay?
We could set the high beam here and all that stuff,
but I'm going to use the control dragging to do that,
so I'm going to hold down control,
and I drag from this guy to this guy, and I'm going
to have the vertical spacing, I'm suing shift, by the way,
vertical spacing, and left, in this case, the left edge,
I want those lined up, and then I'm just going to hit return,
and it created me two constraints for that.
Bottom space and colorful character.
So let's go see what that looks like.
Alright, so we have this, we do stats,
it stays in the lower left.
Whether we're portrait or landscape.
So that worked perfectly, and they stay stacked on each other.
One thing I want to show you is this, watch this.
Let's pick a whole bunch of text here
and make it outlined and colored.
And go to stats.
And you see how these, these nicely show the whole word,
two [inaudible] colorful characters.
In other words, they don't get cut off.
That's because these two things are their intrinsic size.
What happens if, instead, I fix the size of one,
and this is why you're going
to see these intrinsic size being fixed is bad.
So I'm going to take this colorful character one,
I'm going to fix its width and I'm going to do
that by control dragging to itself, okay?
And saying width, I could also do it
with these buttons down here.
And there it is, width equals 157, which is its current width,
I'm just going to leave it that way.
Okay, not let's run and see what happens.
Okay, so it seems like no problem, everything's good.
But let's select a lot of text again.
Oh, not so good.
You see? Since this thing is not its intrinsic size,
it couldn't fit when I went to 127 characters instead of 0.
Right? So it just went dot, dot, dot, I can't fit.
Okay? It always does, you can control this,
but by default it does this dot, dot, dot, if it can't fit.
Okay, so do you see the hazards
of having these hardwired widths in here?
So if I take this and delete it, and run again, now when we go
to the stats, even if we have a lot of stuff, it'll fit.
Okay? Alright, one other thing I guess I'll show you real quick
is [pause] what happens,
let me show you the document outline piece of this.
Okay, so nothing's wrong in here, but I'm going
to make something wrong, let me go to this guy
and let's delete it's aligned leading, okay,
so it's no longer lined up with this.
Okay? When I do that, notice this one turns yellow,
because it is a constraint for an object
that has problems, okay?
So anytime you have an object that has problems,
all its constraints will be yellow, or even red,
if they're conflicting.
So you can see we've got this little red guy here saying
that there's a problem with this guy,
and we know what the problem is, right?
We don't know where it is horizontally, we only know
where it is vertically, okay?
So let's go do that.
And it says needs constraint for X position, again,
I can click on this little red thing.
It'll say add missing constraints, it's smart,
it knows these two were lined up on the left it said,
it's nearby, it said, oh, it probably wants
to be left-aligned, so it put a left align in there.
Okay? One other thing I'll show you real quick,
you see it moved this guy.
Okay? You see how now these are yellow,
because this doesn't match up, this is where the dotted box is,
again, in the outline, if I click this, I have these choices
up here, I'll update the frame to put it back.
One other thing, notice that in all this moving
around this got set to 8, instead of the standard space,
that sometimes happens, I'm not really sure why it lost its
default space we didn't really do anything to specify that,
but you can edit, select and edit, or you can even, okay,
so we could edit here and change this to standard,
or watch this little trick, You see that little guy?
I'm going to double click on that.
Okay, if you double click on a constraint,
all this stuff will appear right you are.
So, in this case, I'm going to switch from 8
to the standard value.
Okay? When I hit return, 8 is the standard value it turns out,
so nothing changed, but just wanted
to show you there how you can double click on a constraint
to set things like it's priority and stuff like that.
Okay? So that's it!
For your homework, you only have a little bit of auto layout
to do because you only have a,
besides the card-containing view, you may have redeal,
add more cards, score, I don't know,
because I let you delete some of the other stuff
from previous assignment.
So, auto layout should be pretty simple for this,
but for the rest of this class, all quarter-long,
you should always be using auto layout.
Your app should always work in landscape and portrait
for the rest of this class, okay, all assignments.
It'll be in the assignments, but, just so you know.
Thank you very much!
>> For more, please visit us at standford.edu.