Transcript
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
[Applause]
Thanks!
>> KEVIN CATHEY: Good afternoon,
welcome back from lunch.
I guess if you guys are watching
the video you are like, lunch,
I'm eating breakfast right now.
Or whatever meal you just
ate, wherever you came from,
welcome to threading
issues with core data.
I'm just kidding.
No, we are here to talk
about interface builder.
My name is Kevin Cathey I'm one
of the interface builder
engineers and we're going
to do something a
little different today,
we're going to show you
some of the new features
of interface builder but I want
to do two other things, one,
we're going to give you
some more advanced content,
tips and tricks, best
practices, interface builder
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
tips and tricks, best
practices, interface builder
under the hood, and then
second we're going to look
at interface builder and how
it helps you through each step
of the development
of your application.
Let me explain a
little bit more.
Here is you.
You have a bright idea.
Now, thankfully there
are some other people
who also think your idea
is pretty bright too,
but here is the problem.
They live all around the world
and they use all different
kinds of Apple products.
What are you doing to do?
First you're going to think
about your application,
what are the features
it's going to have?
What will be the different
clumps of shared functionality
that you're going to have?
When you have those you will
look at an individual scene
and within that scene
you will go down
and actually work
at the view level.
Okay so if we step
back for a second,
going from a view all the way up
to deploying multiple products
in languages, that's
a huge process
and interface builder helps
you save boat loads of time
in each one of those steps.
We can take this entire
process and boil it
down into three main
phases which works out great
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
down into three main
phases which works out great
for an agenda for the session.
We're going to start by talking
about interface builder
at design time.
I'm going to give you
guys some best practices
and then we're going to pull the
hood up a little bit and look
at interface builder
at build time,
and then finally we're going
to spend a large section
of this presentation talking
about interface builder
at run time, both how you can
interact with interface builder
at run time and also how can
you take advantage of many
of the different
run time OS features
for making applications
adaptable.
Let's dive in and start
talking about interface builder
at design time and the best way
to talk about interface builder
at design time is to show
you interface builder
at design time.
Now, before I switch
over to the demo here,
in this demo I'm going to
show you five tips and tricks
and five best practices.
We're going to do that
by adding a new feature
to an application we are working
on which is a road
trip application.
We're going to add a new
tab to it that allows me
to follow my friends who are
currently going on a road trip.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
to follow my friends who are
currently going on a road trip.
In this application, I'm
going to be working off
of a specification from my
designer, and I'm enjoying this
for two reasons, one if you
are working with a designer
to help maybe give you
guys some of the lingo
that you might interact with
when working with a designer,
and then secondly if you're
not working with a designer
to show you that
building applications
and the best processes going
into that can be done with
or without a designer.
With a static mock up
like the one you see
on the screen there's two main
pieces of data you will grab
from this, one, the
layout, where things go.
Two, the appearance,
what things look like.
We're going to start by
working on the layout
of the application,
and that brings us
to our best practice number
one, adopting auto layout
and specifically
adopting stack views.
Adopting auto layout means
taking the relationships
between views and
co-defying those
in objects called constraints.
For those of you who have
used auto layout in the past,
you'll know that working
with raw constraints is very
flexible, very powerful.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
with raw constraints is very
flexible, very powerful.
It's some other things too.
For example, you will sometimes
need to specify the same sets
of constraints repeatedly
and that's
where stack views
come into play.
If constraints are taking
the old, you know, position
and size information
and abstracting
that into relationships, stack
view takes it a step farther
and takes those relationships
and abstracts it into behaviors.
Let's go ahead and adopt
stack view in our application.
Let me switch over to Xcode.
Here is the beginnings of
our awesome new feature.
Adopting stack view in interface
builder literally I don't think
it could be simpler.
I'm just going to select
the views that I want to put
into a stack view and then
using the stack button down here
in the bottom of the
canvas, I just click it,
and now we have a stack view.
Once we have a stack view,
we can adjust several
of the different properties
that a stack view has.
Now, in tomorrow's auto layout
session they're going to go
into all of the different
properties that stack view has
but one that we're
going to focus
on now is called alignment.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
on now is called alignment.
If I switch back to my mock-up,
you can see that my
designer has specified
to baseline a line these labels.
What is baseline alignment?
Baseline alignment basically
allows you to take text
that is different font sizes and
make it look nice and aligned.
If you have textual objects
like buttons and labels
and segmented controls
you're going to want
to baseline align these versus
using top or center or bottom.
So let's go back to interface
builder and what we can do is
if I go into the attributes
inspector I can change the
alignment of my stack view
to be baseline aligned.
Now, there is first
and last year,
so if you have multi-line text,
you can target either
the first line of text
or the last line of text.
In this case it's single line
so it doesn't really matter
so we'll go with first.
Wonderful.
So let's continue adopting stack
view, I can take this stack
in this label and
put it in stack view
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
in this label and
put it in stack view
and I can add our image view.
As I'm embedding in stack view,
interface builder is
automatically inferring the
different attributes such as the
alignment and the orientation.
Now that we have this
outer stack view we want
to position this
within our table cell
which is not a stack view.
And to do this we're going
to use raw constraints.
I'm going to go to my tie
fighter and go ahead and open
up add constraints and I
want to clarify two things
in this pop-up, the
first is what is
up with the layout margins?
What are these things.
Layout margins are
insets from a view
that by default the system
provides some values for
and if you use the default
layout margins they can be
automatically adapted based upon
different context, for example,
the device or the
view hierarchy.
Generally if you have
content like buttons, labels,
things that people interact
with or see, then you are going
to want to constrain
things to the margins
if it's not constrained
to another sub view.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
if it's not constrained
to another sub view.
If you have something like
an image view that kind
of sits behind your
entire table view cell
that makes perfect
sense to constrain it
to the edges instead so even
if those margins change
your imagery will still be
in the background.
If I uncheck constraints,
constraints
and margins you can see larger
values coming into play.
Interface builder defaults
to margins which is helpful
because that's exactly
what I want.
Second thing I want to clarify
is this update frames here
which I am going to use.
Update frames is the process
of interface builder moving
your views in the IB canvas
to match what the constraints
would be at run time.
When I'm adding constraints
I have a couple
of options for doing this.
If I say all frames in
container it means for all
of the sub views in
my table view cell,
move them to where the
constraints would tell them
to be at run time.
However, if I have a really
large view with lots and lots
of sub views, I might only
want to move the things
that I'm currently working
on at that instance,
and that's what this
middle option is,
it only moves the items that
are actually going to be
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
it only moves the items that
are actually going to be
in the new constraints
I'm adding.
Now, I only have one
thing so it doesn't matter
so we will do all frames
and add those constraints
and now we are on our way.
Okay. Next thing I want to
do is change the alignment
of the items inside
the stack view.
Another example of doing that.
I will change that
to fill and now,
that's not exactly what
I'm looking for, right?
Stack views are built
on top of auto layout,
which means that you
can use constraints
to fine tune your layout.
So if I want to make this image
view have a one-on-one ratio,
even though it's
in a stack view,
I can still add constraints
so I can add an aspect ratio
and then change the
multiplier to be one to one.
The next thing I want to do
is add spacing in between
that image view and
the right hand content.
Because my designer would like
there to be some padding there.
Now, the stack view that I
need to change the spacing
on is fully occluded by
labels and other stack views?
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
on is fully occluded by
labels and other stack views?
How can I get at it?
There are a couple
of ways you can get
at occluded views in
interface builder.
I could use the jump bar or
I could use the outline view,
but I'm going to show
you my personal favorite
which brings us to
Xcode pro tip number one
which is fast selection.
If I shift right click
or control left click.
I can get a menu of
everything underneath the mouse
at that point and then I
can easily select the thing
that I'm looking for.
Once I have it selected
I can change the spacing
to what I need and there we go.
The last thing I
want to show you
with stack view is how you can
use multiple stack views nested
together to get the exact
layout you are looking for.
If we go back to our
specification here,
you can see this set of labels
our designer would like it
to act as a unit and
be centered vertically
within the table view cell.
We can do this by putting
the right hand content
in another stack view and
adjusting the alignment.
Let me show you that.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
I will use my fast selection
again to get to the stack view.
I'm going to embed it
in another stack view.
You can see the blue got a
little darker to show you that,
and now I can change
my alignment to center.
Now, alignment affects the
non-stacking direction.
Because this is a
vertical stack view,
it's going to be adjusting
the horizontal alignment,
but I want to affect
the vertical alignment
so I will change the
access to horizontal.
And you can see with stack views
I can get the exact layout I'm
looking for with very
minimal constraints.
Our recommendation when
adopting auto layout is
to use stack views and to
try to use stack views first
and then only when you need to
actually use raw constraints.
We think you're going
to be able to build most
of your UIs using stack views.
Which makes it easy to build.
It makes it really
easy to experiment
with different layouts without
having to adjust a bunch
of constraints and it also
makes it very maintainable
when you go back
in later and have
to edit one of your documents.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
to edit one of your documents.
The next thing we want
to do is start looking
at the appearance
of our application.
And the first thing I'm going
to do is prepare our
canvas for some design time.
To do this I'm going to go
under the edit canvas menu.
And interface builder
has lots of options
for customizing what's
drawn on the canvas.
For example, these blue
backgrounds the stack view is
drawing for me are really
helpful at layout time
so I can see exactly how big
that stack view is going to be,
but at design time I want to
see what it's actually going
to look like at runtime.
So I will just go ahead
and turn those off.
Okay. In the appearance section
of this demo, we are going
to look at three best practices
with using interface builder.
If we go back to
our specification,
we'll see the first one.
Our designer has specified
headline and body instead
of an explicit font
or font size.
What are these?
These are called
dynamic type styles.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
These are called
dynamic type styles.
They are defined by the
system and when you use them,
it allows the system
to automatically adapt what the
effective size and font is going
to be at runtime based upon
your user's preferences.
For example, the user
can adjust accessibility
to have a larger font.
Your application when using
dynamic type will automatically
adapt to those font changes and
if you are using auto layout,
the views will all
flow around it.
So we can adopt this
really easily inside
of interface builder.
I can just select the label I
want to adopt dynamic type for
and the inspector,
I can pick one
of the font styles instead
of an explicit font.
In this case, I will
choose headline.
I have already adopted it
for the rest of my labels
so we are done with
dynamic type.
The next thing we are going
to do is we are going to bring
that image view to
life and we are going
to use two best practices
for this.
One is designables, and
two is inspectables.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Designables allows us to see our
custom drawing code right inside
the interface builder canvas.
So let's go ahead and
get some code for that.
I want to go ahead and open
up the product navigator.
Let's add some files.
Tony, who is going to come
up later just air dropped me
this code, so let's go ahead
and add that to our project,
and I'm going to go ahead
and open this, and
in opening it,
I'm going to show you guys
Xcode pro tip number three,
which is advanced navigation.
If I option shift click this
file, I get a little hud.
This hud allows me to target
where I want to open this file.
So I can choose a new tab,
I can choose a new split.
If I have multiple tabs I can
even target specific splits
within tabs that
aren't even open.
And as I use command I can also
even open it in a new window.
In this case, I'm just going
to do the assistant editor.
Adopting designables is a
really simple two step process.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Adopting designables is a
really simple two step process.
All you have to do is
mark a subclass of UI view
with IB designable, and
then set that custom class
with an interface builder.
So if we select our image
view or what's going
to be our image view, change
the identity inspector,
and add in our customs
subclass here.
Interface builder is
going to build my project,
launch a process for rendering,
bring in my code, render it
and show me that in the canvas.
And if I change the code,
it's going to automatically take
those new changes, build them,
and apply them within
interface builder as well.
The next thing I want to
go is adopt inspectables.
You can see I have a couple
different properties here marked
add IB inspectable.
When you mark a property
as IB inspectable it
allows interface builder
to generate an inspector
for you.
If I select image view, go
to the attributes inspector,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
If I select image view, go
to the attributes inspector,
you can see that those
three properties I marked
as inspectable are showing
up now in our inspector
and we can quickly adopt these.
So I can say I'm going to
add that little image there.
We're going to do
our stroke with.
I think the spec said two,
if I recall correctly.
And we can give it a nice
border color as well.
Now, what's going on
here is that designables
and inspectables
are working together
to help you rapidly
iterate on your design.
I haven't built and ran once and
I can see exactly what I'm going
to get at runtime
because of the power
of designables and inspectables.
And that's our section on
adjusting the appearance
of our application
with the dynamic type,
designables and inspectables.
Now, we all know that our
applications are not made
up of a single scene, okay,
unless you write the flashlight
app, but generally you're going
to have multiple scenes
in your application.
And if I zoom the storyboard
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And if I zoom the storyboard
out I can see there is a lot
more scenes in my application.
You can bring a scene
into the flow
of your application
using segues.
To make a segue I can control
drag from a view controller
or an object that can initiate
a segue and select the type
of segue I want to add.
In this case I will add
a relationship segue
to add another tab to
our tab bar controller.
Now, once we actually have made
the segue, I realize that I kind
of want to be able to navigate
within this table view
controller, so I am going
to embed this in a
navigation controller.
I will choose the editor menu,
embed and embed this inside
a navigation controller.
I want to point out something
that interface builder
is doing to help us here.
This is another Xcode pro tip.
Interface builder is showing
us a nav bar and a tab bar
for this particular scene.
Now these objects are
not added to the scene,
interface builder has not
added these to your scene
but what it is doing is helping
you see what your application is
going to look like at
runtime given some context.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
This makes it really
easy to be able to design
for different contexts without
having to build and run.
You can see what your simulated
metrics are, which is the name
of the feature, by selecting
your view controller.
And then going to the
attributes inspector
and you can see my
simulated metrics.
Now, right now they are
all saying inferred.
Inferred just basically means
use the context around me.
We know we are inside
a tab bar controller,
we know that we're
inside a nav controller
so interface builder
knows which bar to show.
I can override these
to be whatever I need.
So, for example, I could
say actually I want to look
like what is it going
to look like with prompt
if I had prompt text in there?
What if the top bar was black.
I will put this back
on inferred.
All of these metrics do not
affect your actual application
at runtime with one exception
and that's the size
simulated metric.
The size simulated metric
will actually change the size
of your view controller but
generally you're going to put it
into a view controller
hierarchy which will resize it,
but it's also helpful if you
are creating free form view
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
but it's also helpful if you
are creating free form view
controllers, for example, and
want to set your own size.
It's also helpful if you are
wanting to be able to design
with a specific size
in mind even
if your application is going
to run on multiple devices.
The spec I was given was for
iPhone 6 Plus, so I can change
to a 5.5 in screen size
and be able to edit
as if the view controller
was going to be that size.
There's other features
of interface builder we are
not going to talk about today
which allows you to see what
your view controller will look
like on multiple devices
at the same time using
the preview assistant,
but this is really helpful
for just being able to edit
with a particular
context in mind.
All right.
Let's go back to inferred
and let's finish off
our view controller.
Give it a title, your friends.
Let's add some bar button items.
We had add one for being
able to invite a new friend.
And with Xcode 7 I can
add multiple bar items
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And with Xcode 7 I can
add multiple bar items
to my navigation item.
[Applause]
It's the small features, right?
[laughter]
Let's finish off this
by adding a segue
to present this guy
modally, and if you zoom
out we have a great start
to your application.
Just like I would
refactor my code
into separate files based
upon the reuse of it
or related functionality,
I can do the exact same
thing now with interface.
If I just select the view
controllers that I want and go
under the editor menu, I can
select refactor to storyboard.
You can type in a name,
I will call it follow
because this is our follow tab.
Interface builder is going
to create a new storyboard,
move those view controller
scenes into the storyboard
and put a reference to the
scenes in the old storyboard.
Now, it's really easy to
collaborate with storyboards.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
[Applause]
And it's the big features.
[laughter]
Let's go back to slides.
We have looked at a number
of different things
here so let's recap.
All right.
I have given you
five best practices.
We have adopted stack
views and dynamic type
to make your applications
adaptable.
We have adopted designables
and inspectables to be able
to rapidly iterate
on your design
without having to build and run.
And finally we have used
storyboard references
to make sure we are properly
modularizing our interface just
like we would do for our code.
I have also given
you a couple of tips
that I hope you guys
are going to find useful
as you're using interface
builder like being able
to select things, being able
to customize the canvas,
open files exactly where you
want them using multiple bar
items and, of course, taking
advantage of simulated metrics
to see at design time what you
are going to get at run time.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
But what happens
when I hit build?
Let's talk a little bit about
what interface builder is doing
for you at build time.
Now, to do this we are going
to have to take a step back
and look again at design time
and where we are
going with run time.
At design time you are
working with XML documents.
At build time a process called
IB tool takes these documents
and compiles them
into nib files.
Nib files are small, very
optimized binary files
and it uses a process
called keyed archiving
for creating these.
I have a few examples of
what this could look like.
When interface builder is
compiling a storyboard it's
doing two things first,
it's trying to maximize the
performance of your application
and secondly it's also
minimizing the number
of nib files created.
If I have a view controller with
a view and a bunch of sub views,
interface builder, the
build time is going
to create a nib file
for the view controller
and create a nib
file for the view.
Why two nib files.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Why two nib files.
By having separate nib files
for both the view controller
and the view, this means the
view hierarchy can be loaded
on demand.
With this other example here,
with the table view controller
and navigation controller
things get even a little
more interesting.
Again, interface builder is
trying to minimize the number
of nib files it's creating with
a relationship segue we know
that those two view
controllers go together,
so we will put those
in the same nib.
Next we are going to give you
a nib file for the table view
and also a nib file
for each of the cells.
So how does this
play out at run time?
When you allocate a storyboard
instance using UI storyboard,
API, initially all you
are allocating memory
for is the UI storyboard
instance itself.
No view controllers
no views yet.
When you instantiate your
initial view controller it will
load the nib for that initial
view controller but, again,
no view hierarchy
has been loaded
yet until someone
actually asks for it.
Similarly, if I gave that
navigation controller
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Similarly, if I gave that
navigation controller
and table view controller an
identifier then I could use the
instantiate API to
be able to get
that view controller
instance, but, again,
the view has not been
loaded into memory
until someone actually
asks for it.
How about those table
view cells?
This is where it gets fun.
So interface builder is going
to automatically take table view
cells, nibs, and register them
with the table view under
your reuse identifier
that you set, that
table view cell.
Now, what this means is that
these cells are not going
to be loaded until someone
actually DQs the cell
with the identifier.
Now, it also means that once
the nib run time has loaded
that nib file into memory, it
can rapidly instantiate it.
So there are a couple of
take aways for talking
about interface builder
at build time.
The first is performance.
Interface builder is
working on your behalf
to make the performance of your
applications as good as we can.
Nib files are only
loaded on demand
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and nib files themselves are
really small and optimized.
Secondly, interface builder has
reuse of different nib files.
For example, on the table
view cell that's we saw,
once the runtime has
the nib file it's able
to reinstantiate it very very
quickly as new cells are needed.
Finally hopefully you
can see the lifecycle
of how things are happening
between build time and runtime
so you know how to interact
with the different objects
like your view controllers
and your view hierarchies.
We talks about interface
builder at design time.
We have pulled the hood up
a little bit at build time,
but we're going to spend the
rest of the session talking
about interface builder at
runtime and what happens
when you have all those
different products
and languages.
To do that, I'm going to bring
up my colleague, Tony Ricciardi.
[Applause]
>> TONY RICCIARDI:
Thank you Kevin.
Good afternoon.
My name is Tony, and I also
work on interface builder.
So Kevin just gave you
some great best practices
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So Kevin just gave you
some great best practices
for building your UI at design
time and then he gave you a peek
at what happens behind
the scenes at build time.
Now, I'm going to give
you a few examples
of how you can add dynamic
behavior to your UI at run time.
Interface builder supports
three general mechanisms
for controlling your
UI at run time.
First of all, you can
create connections
between your storyboard and your
source code using IB actions
and IB outlets.
You can also customize the
behavior of your segues
or dynamically instantiate
and add view controllers
using the storyboard API.
And finally, you can use
auto layout or size classes
to specify how your
UI adapts as the size
of its container changes.
Let's start with connections.
In Swift, IB outlets are
by default implicitly
unwrapped optionals.
If you have an outlet between
a view controller and one
of the views in its hierarchy
you can safely unwrap
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
of the views in its hierarchy
you can safely unwrap
that optional after viewed load.
Sometimes you will have an
additional property stored
on your view controller
that affects the appearance
of that view, and in that
case, you will want to unwrap
that property using
optional chaining
within the did set
observer of that property.
In case your outlet
hasn't been connected yet.
IBAction is allowing you
to respond to events sent
from gesture recognizers
and controls.
You might use an action
just to update some state
without navigating away
from the current view.
You can also use an IBAction
to dynamically choose
which segue you want to
perform after an event.
Next we have the storyboard API.
The class UI storyboard or NS
storyboard on the Mac allows you
to grab a reference
to a storyboard file
and instantiate view controllers
from that storyboard.
It's extremely useful if
you have a reusable piece
of UI you want to
repeatedly instantiate.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
It's also the only way you can
connect multiple storyboards
in your app if you
are displaying prior
to iOS 9 or Mac OS 10, 11.
We also have a lot of great
API hooks on UI controller
to allow you to customize
behavior of your segues.
This year we have made
a lot of improvements
to segue unwinding on iOS.
We have made it a lot easier
to subclass UI storyboard segue
or NS storyboard segue.
If you would like to
learn more about that,
please come to our What's New
in Storyboard session
tomorrow morning.
Finally we have adaptability.
Interface builder
supports two technologies
to help you adapt your UI to
different container sizes.
First of all, we have auto
layout which allows you to size
and position your views
relative to each other
so that you are not relying
on hard coded frame values.
In some situations,
you will want
to make a significant change
to your layout as the width
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
to make a significant change
to your layout as the width
or height of the container
crosses a certain threshold,
and in those situations we have
another great feature called
size classes which makes
that very easy to do.
Now, I would like
to give you a demo
of how you can apply these
three general techniques to work
with interface builder
at run time.
Let's head over to Xcode.
Today we will be building a UI
to keep track of the activity
of your friends on
their Roadtrip and plan
on integrating this into
Kevin's Roadtrip app later on.
As you can see in this UI,
I have three rows of posts,
and within each row, I
show the top three posts
from that category.
If we take a look at the
storyboard for my app,
you can see I have implemented
this UI using a stack view.
Within this stack view, I
have three container views.
A container view allows you to
embed one view controller inside
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
A container view allows you to
embed one view controller inside
of another one, and
that's extremely useful
if you have a reusable piece
of UI like this that you want
to use multiple times
within the same scene.
My embedded view controller
over here has a stack
view of its own.
In this stack view
holds multiple instances
of this post view
controller down here.
The number of posts that I show
in each category is controlled
by a user setting and so
I don't know it statically
at design time.
Instead of using container
views like I do over here,
for this view controller,
I instantiate it using
the storyboard API.
I refer to this view controller
from code using its storyboard
ID up here which I have set
up here in the identity
inspector.
Let's take a look at the
code where I do that.
I'm going to use the jump bar to
navigate to the source code file
for my post stack
view controller.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
All right.
So you can see down here
in my view.load method I'm using
the storybook API instantiate
that post view controller.
Specifically, I'm using
the storyboard property
that I'm getting from
UI view controller
and then I'm calling instantiate
view controller with identifier.
And that identifier I pass in
is the same string we just saw
in the identity inspector.
After I add or after I
instantiate the child,
I add it as a child
view controller.
And then I add it's view
as an arranged sub
view of my stacking.
So the storyboard API is
great for instantiating
and adding a child view
controller, but what if you want
to add a sub view
that is not associated
with a different
view controller.
Let's head back to the
storyboard for an example.
If we take a look
up here at the top
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
If we take a look
up here at the top
of my activity view controller,
you can see I have a view
up here in the scene doc.
The scene doc allows you
to store top level objects
alongside your view controller
and you might put a view in
your scene doc if you don't want
that view to initially be
part of your view at run time.
In Xcode 7 when you put
a view in your scene doc
and you select it, it
shows up in its own editor
above the view controller.
[Applause]
This means you can now visually
edit your views right here
in the storyboard canvas, even
if they are not initially part
of your view hierarchy.
This view here shows
an error message
if there is a problem
connecting.
So what I want to do now is
create an outlet connection
to this view and
then add it from code
if there is a problem
connecting.
I want to open up the assistant
editor and that's going
to take me to the implementation
for my activity view controller.
And then I'm just
going to control drag
over to the source code and when
I let go, I get a little pop
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
over to the source code and when
I let go, I get a little pop
over allowing me to configure
my outlet connection.
But -- the first option
here is whether I want
to make an outlet or
outlet collection.
Outlet collections are great
for adding or removing groups
of sub views or constraints
all at once, but in my case,
I just want to add
a single view,
so I'm going to choose outlet.
Next we can name the connection.
I'm going to call it
connection error view.
And the last option I want to
point out is the storage type,
which can either
be strong or weak.
In general you should
make your outlet strong,
especially if you are connecting
an outlet to a sub view
or to a constraint that's not
always going to be retained
by the view hierarchy.
The only time you really need
to make an outlet weak is
if you have a custom view
that references something back
up the view hierarchy and in
general that's not recommended.
So I'm going to choose strong
and I will click connect
which will generate my outlet.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
which will generate my outlet.
Now, I'm just going
to paste in some code,
and this code is an
implementation of view did load.
And I check if there is a
problem connecting and if it so,
I add my connection error view
to the top of my root stack view
and I'm accessing both
views using outlets.
Let's take a look at
this in the simulator.
So as you can see, there
was a problem connecting,
and now my view is showing up
right at the top as we expected.
So this UI looks great
on a full screen iPad.
What happens if I
run it in split view?
I'm just going to drag the
split to be in the middle
of the screen and let go,
and you can see my UI
is not doing a great job
of adapting to the narrow width.
What I really want is for these
posts to lay out vertically
when the width is compact
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
when the width is compact
so that each post can
get the full width
of the screen to itself.
And at the same time, when we
are back in full screen mode,
I want my stack views
to continue to lay
out horizontally
like they are now.
So to do that, I'm going to
head back to my storyboard,
and I'm going to
close the assistant
to give us a little more room.
And I'm going to select
my stack view and head
over to its attributes
inspector.
You can see currently my stack
view is configured to lay
out horizontally, and next
to this access property
there is a plus button.
This plus button allows you to
add a size class customization.
A size class is an abstract
range of sizes in one
or two dimensions
and in my case I want
to customize this property
for when the width is compact.
And since I don't care
about the height dimension,
I will choose any height.
When I do that, I get a
new row in my inspector
and the value I put here
is going to take effect
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and the value I put here
is going to take effect
when the width is compact
and the height is anything.
I will change that
to vertical now.
And I will run this again.
So once again we
are in full screen
and our stack views are still
laying out horizontally.
Now, let's try this in
split view mode again.
All right.
We got it.
So there you go, now our
accessory view is laying
out vertically like we wanted
and each post gets the full
width of the half screen.
[Applause]
So that was just one way
you can use size classes.
You can override a property
value for single property,
but you can also add and
remove entirely new sub views
or constraints, and if
you want to learn more
about all you can do
with size classes,
we had a fantastic session
on that last year called
building adaptive apps
with UI kit.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
with UI kit.
That's all I have for the demo,
so let's head back
to the slides.
Kevin and I just showed you
a ton of great techniques
to help you get the most
out of interface builder.
Let's review the
most important ones.
First of all, you saw how
you can build flexible user
interfaces that don't rely
on hard coded frame values
using auto layout constraints
and stack views.
Then Kevin showed you how
you can rapidly iterate
on the appearance of your
custom views using designables
and inspectables.
We introduced a new feature
to help you modularize your UI
called storyboard references,
and then I showed you how you
can use the storyboard API
to repeatedly instantiate
reusable components.
And finally, you saw how
you can make your UI adapt
to different container
sizes using size classes.
If you would like more
information, you can post
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
If you would like more
information, you can post
on the forums or
contact our evangelist
and we also highly recommend
checking out our What's New
in Storyboard session
tomorrow morning as well
as our two auto layout
sessions later that day.
Once again if you
want to learn more
about size classes please check
out our building adaptive
app session from last year.
And finally if you
want to learn more
about troubleshooting
your auto layout
within Xcode we had a great
session on that in 2013.
And thank you all and
please enjoy the rest
of the conference.
[Applause]