[ 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.
