WWDC2013 Session 405

Transcript

X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
[ Silence ]
>> Good morning and welcome to
Interface Builder Core Concepts.
My name is Kelly Keenan and
I'm going to be stepping you
through the first
half of this session.
Now, what we're going to be
doing today is talking about how
to get started creating
fantastic user interfaces using
Interface Builder
inside of Xcode.
So, the way that we build
interfaces in Xcode is
by dragging and dropping
actual live controls and views,
and then configuring them
and making connections
between those views and
controls and your code.
So, it's perfectly
normal to write code
to design your user interface,
and this code does just that.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
For example, it creates
an image,
and then it creates a button,
and then it adds the image
to the button, it sets the
buttons target in action
and it adds the button
to the window.
Now these are really simple
things that you're going
to do over and over again.
And in this case, what this
code actually does is it creates
that little info button in
the corner of the window
and so we want to
make things like this,
something that you're
going to do over
and over again that's
easily repeatable.
We want to make this easy
for you within Xcode.
So, let's take a little tour
of Xcode and what we're going
to be talking about today just
that we have the same vocabulary
when we're speaking
of these things.
The first thing is
going to be our canvas.
Our canvas is in the center
and this is where we drag
and drop our controls and views.
And we manipulate them
by resizing them or
editing the text.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Next is the document outline.
Document outline shows you
all of the views and controls
that are in your interface.
Sometimes, you'll notice that
some of your views are obscured
by other views and they
might be hard to just click
on them in the canvas.
Use the document outline to
access these items easily.
The third part are
the inspectors,
and the inspectors
are where you're going
to edit the properties of
your views and controls.
So, there's a lot of step
you can do in a canvas
but this gives you the
fine-grained access to all
of the properties
of those objects.
And lastly is the
library, and the library is
where we give you a bunch of
pre-made views and controls
that you can use and just drag
and drop on to the canvas.
Now the way we work in Xcode is
by using the
Model-View-Controller paradigm.
You've probably mostly familiar
with this and what we're going
to be talking today about
is mainly the view and how
to design your view, but also
the view doesn't do much all
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
by itself.
It looks pretty but
there's nothing behind it,
unless you add a controller,
and that controller is your
personal code that's going
to do something when the user
interacts with your interface,
and it's going to be used
to display information back
to the user in your view.
So the other part we need to
talk about is how to connect
to these two, how to connect
the view to the controller
and make your views interactive.
So in Interface Builder,
what we use are storyboards,
and storyboards are a collection
of these views and controls,
and I want to remind you,
these are actual live objects.
These were not writing code
behind that's creating these
objects later.
When this is saved
out and compiled,
they're actual live
objects so that
when you load your
storyboard, you get an instance
of that object and
that's important.
There is no hidden code that
you're going to want to go find.
Now, storyboards are made of two
pieces, the first being scenes.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Now scenes are like a screen
of your iPhone or a portion
of the user interface.
So, these are two
examples of scenes.
We have two scenes here.
And in order for the scenes
to talk to each other,
we have something
called a segue,
and a segue represents
how to move
from one scene to another scene.
It also allows you to say, "OK,
I'm about to move from one scene
to another scene, and I need
that other scene
to get some data.
So now is the time I'm
going to push that data
over to my other scene.
OK. So, what I'd like
to do is go through--
the best thing to do
is a demo application.
So, we're going to just
create a simple user interface
and we're going to
change some properties.
We're going to learn how
to resize and align objects
and hopefully give you
some tips and tricks
that maybe you didn't
know about already.
And we're going to learn how to
make connections between scenes
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and between the scenes
and your code.
And what we're going to make
is this application here.
You've seen it in previous
demos and we're going
to start from scratch with it.
And we're going to do
this welcome screen
with the two buttons,
the timer and the routes,
tomato, it's up to you guys.
We're going to work on the
timer button so I don't have
to pronounce the
other word again.
So, then when you press the
timer button, it's going to go
to this run scene
and show you a timer.
We can hit the pause button.
It's going to change
and we're going to make
that all happen right now.
So, let's get to our demo.
So, we're going to start right
from scratch and we're going
to create a new Xcode project.
Now, in our project, Xcode gives
you some really basic templates
that you can work
with and what we try
to do is give you those
things that you might want
to start your application
of with,
it's like a Master-Detail
Application
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
or a Tabbed Application.
But what I want to show you is
if you start with a single view,
how you can create and expand
that into something else.
So let's start with just
a single view application.
And I'm going to just give it
a product name and we're going
to call it Jagger and
this where you're going
to set your company identifier,
your organization,
and the new devices.
In this case we're just going
to use an iPhone app for today.
So, click next and we're just
going to save it on the desktop.
So, the first thing that you see
when you create a new
project is you're going
to see the project settings.
And there are some things in
these settings that are specific
to your user interface, and
I want to point those out.
So, specifically, within
the deployment info--
oops, sorry, within
the deployment info,
you can sub the devices but
the thing I want to point
out is the main interface.
Now you might have wondered
in the past when you start
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
up an application on your
phone, how does it know
which storyboard to start with?
That's set here in
the project settings.
So if you had multiple
storyboards, you would be able
to change this to a
different storyboard
if you wanted your
application to launch
with the different
storyboard than the main one
that was created
with the template.
Also, if you might need to load
your storyboards based on code.
You might need to say
is this iOS 6 or 7
or what storyboard do
I want to start with.
And so, if you want to load
your storyboard from code,
you're going to delete this
and just leave it blank.
OK? Now, you can also set
your device orientation,
your status bar style,
and here are the app icon
in the launched images
that are used
when your application
is starting up.
Now speaking of images, we have
an image or asset catalogue
and that app icon in the
launch image are available here
in the catalogue.
Now these are empty and what
I want is my designer actually
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
gave me a bunch of images for
me to work with today on stage.
So I'm just going to delete
the empty ones for now and drag
in the images I was given.
Drop them in there.
So now these are images that
we're going to be able work
with today during
our project demo.
So let's go to the
storyboard and I'm going
to bring this full screen and
hide the project navigator
for now because we're not
going to need it for a while.
So, what I said earlier was
that these are live objects.
We can drag them around
and we can move them.
This is a view controller,
this is my first scene.
And the way I know that this
is the scene that's going
to be seen when my app launches
is this error right here
that points to the
RootViewController.
Now, I showed you
already that I'm going
to press the timer button and
I'm going to go to another scene
and I want that scene to be able
to go back to the first scene.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So I'm going to need something
called a navigation controller.
And so, now that I've decided--
oh, I don't just
want single stand,
I want a navigation controller.
I want to be able to embed this
into a navigation controller.
So with my view controller
selected,
I can go to the Editor menu.
Now the Editor menu has all
of these specific actions
that are available
to Interface Builder.
So these changes depending
on what editor you have open
whether it's Interface Builder
or a source editor.
And in this case I want to embed
in a navigation controller.
So, now the scene that we're
going to work with is inside
of this navigation controller
and they are connected
by a relationship.
And if we want to see exactly
what's going and we can open
up the document outline with
the button in the bottom corner,
we can see exactly
the objects that are
in my storyboard at the moment.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Now, that application had
a really great background
and that was one of
those images I was given.
So, the first thing I want to do
is add that image to our scene
and you can find all of the
images that we have added
to the asset catalog
are available here
in the media library.
So, you'll see these are
all the images that I added.
So, we can easily just drag
out the background and drop it
on to our canvas, move
it around a little bit,
and we also want to add a title.
So I can drag out the
title and I'm just going
to place it here for now.
I'm not going to worry about
placement for the moment.
So the next thing we
needed are two buttons.
So, I'm going to go to
the third library here
which is the object library
and the object library is
where you're going to see
all those controls and views.
So we can scroll through
and look for things that way
or you could just type
in the filer field.
So we can type in "button" and
I see I have my button here.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Now, I can drag my button out
and drop it on to my canvas,
and you'll see I have a
nice little button here.
I can double click it if
I want to edit the title.
So I could change this
to timer if I wanted to.
In this case they don't
actually want a title.
And so, I'm going to delete this
title right now and I want it
to have that image
of the little clock.
So, I can go back to
media library and drag
out the timer button
and drop it in.
So, at this point, I need
a second button as well.
And so, I'm just going to
duplicate this with command D
and create a second
timer button.
And you'll notice
as I move it around,
there are these blue lines.
Maybe I can zoom in a little
more so you can see them.
There are these blue lines
that show up and my button kind
of snaps to them as
I move it around.
These are called guides and
they're really useful to be able
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
to get your user
interface elements
in the correct position.
So, this way, I now know these
buttons are properly space.
If I select both of them at
the same time, I can move them
around and now center them.
And another thing is that my
designer said he wanted these
buttons to be 34
points from the bottom.
So, how exactly do I get them
34 points from the bottom?
Well, there's a little secret,
I don't know if you guys know
about this yet but
hopefully you do,
if you hold down the option
key while you have something
selected and move
your mouse around,
it will actually show you
how far your items are
from other items.
So, in this case, we're
48 and I want to be 34.
And so I can use the
arrow keys to just move
down to 34 points, great.
And the last thing is I want
this title to be centered
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and I want it right
above the buttons.
So, that's laid out,
but I haven't changed
that other timer button, it
needs to be a routes button.
So, I can just drag
the image in,
drop that in, and
we're good to go.
So, this is our welcome screen.
Looks great, does
nothing at this point.
And the first thing we want
to be able to do is move
from that timer button
to our new scene.
So, in order to do that, we're
going to need a view controller.
So, if I go to the objects
library, I can just type
in view controller
and I can drag one
out onto my canvas here.
Let's scroll out a little.
So, now I have this new view
controller on my canvas,
that's going to be
that second scene.
And in order to connect from
the timer to this new scene,
the timer button to this
new scene, I'm going hold
down the con-- I'm going
to select the timer
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and then hold the control
key while I'm dragging
to the new scene.
And when I release, what I'll
see is I'm given three choices
for a segue, either a
push, a modal, or a custom.
And I'm going to choose
push and when I do,
we have our segue created.
So now, when I hit that
timer button, there is going
to be a push segue to
bring out this new scene.
So let's design the new scene.
There is some more images I
was given, one of them was
that circle up at the top that
the label for the timer was in.
So, I'm just going to
center that in here
and you can see I'm
using the guides.
I need a button down at the
bottom, so I'm just going
to copy and paste the button
that I have already
and then change it.
So, do paste.
Now, again, I want this
button instead of 34,
the designer said
this one has to be 56.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So again, I can hold
the option key down.
I can-- to make sure
it's centered first.
OK, hold the option
key and I can check,
and I can move it exactly to
where I was told that should be.
And it's not going to be that
button; this one is going
to be a pause button, so
I just drag my image in.
OK, so the next thing I need is
to change the background color.
So, my view, I can't
change the background just
by editing it on the canvas.
So far, everything we've
done has been on the canvas
and just dragging and dropping
and manipulating things.
But I need to change the
background color for this view.
So I'm going to open up the
Attributes Inspector up here.
And when I do, you'll see that
these are all the attributes
that are specific to view.
And in this case, we can
let the tool tip come up.
This is the background color.
The tool tips will give you
some related method information
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
which can be useful if you're
just getting used to this.
So, I'm going to click
on the background color.
Now, I've already set
one up and I've left it
in my color swatches,
so, ready there.
And the next thing we
want to do is add a label.
So I'm going to go back
to the object library,
select the Label, and let's
drag this in a little bit
so you can see better.
So, when I drag this out, one of
the nice things is that as soon
as I move the label on
to this dark background,
it's going to change
color to light knowing
that you don't really
want a dark label on top
of a black background.
Now, this label is
really small so I'm going
to make it a lot
bigger right now.
And I need to change
the font size so that,
you know, it's easily seen.
So, I'm going to
go to the inspector
or the Attributes Inspector
again, and now you'll see
in addition to View,
I have Label.
So, all of the controls in
the Attributes Inspector,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
all of the properties are
separated by hierarchy.
So you're going to see the
things that are specific
to UILabel first and then
its super class UIView will
come next.
So, in this case, I want to
change the font and I can click
on the font picker, change to
system bold, and I want 36.
OK, great.
Now, I wanted to default
to looking like this,
and I want to center
it inside of my circle.
Now, you'll notice it's not
really centering correctly
and that's because the
label is much bigger
than the text that's inside it.
Now, we could resize by
moving around and trying
to get just the right size,
but I don't really know
what the right size is.
Now, it's possible I
might know how this--
like I might know the
pixels for it, so I could go
to the Size Inspector, and if
I click there, that's going
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
to show me the position of my
object as well as the width
and the height, and
some other information.
So, I could set it
specifically here,
but one of the things I
really want to tell you
about right now is
in the Editor menu
which is Size to Fit Content.
And I use this all the
time, command equals.
And when I click on that,
it just resizes the label
to fit the title
that's inside of it.
So, now when I drag it around,
it'll center properly
to the actual label.
Great. So now we
have all these--
we have our views laid out,
I think I have all the buttons I
need and the label that we need,
but it's not going
to do anything.
The timer is not going to run,
if I press the Pause button,
nothing is going to happen
unless I've put some code
behind this.
And so, the next thing we
need to do is create a class
to control this view controller,
so, well, to control this view.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So right now, if I click
on the view controller,
I can go up here to
the Identity Inspector,
you'll see that this view
controller is a UIViewController
but we really want
our own subclass
where we can do our
custom work inside of it.
So, back in, I'm going to
close the document outlines
so we have a little RIM, and
back in the project navigator,
I'm going to go ahead I'm
going to add a new file,
and in this case, I want to
add an Objective-C class,
we're going to call it
RunViewController and it's going
to be a subclass
of UIViewController
'cause we just want to add
on to the UIViewController.
I click Next, and I want
to make sure that it ends
up in the target for my
project and I can create.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So now you'll see I have some--
when I create this new file,
I've given-- I've been
given some code to start
with specifically and
it wouldn't have name.
So, when you-- the nib that's
created when you compile,
this is where you do any
custom initialization.
You can also access viewDidLoad
and didReceiveMemoryWarning.
So these are places where if
you needed, you custom things,
you can do them right here.
So I'm going to leave that
and go back to our storyboard.
Close the project navigator
'cause we don't need
that any longer.
And-- sorry, this view
controller, I want to make sure
that instead of a
UIViewController,
I want it to be a
run view controller.
So now, when this object is
archived out when we save it,
when it's instantiated later
it's going to come back
as an actual run view
controller instance.
So, I can open up my Assistant
Editor now and we're going
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
to make a little
RIM for our code
and then show just our view.
Now, I want to be able access
this user interface items
within my code itself.
And the first I want to be able
to access is this time label.
So, I need something in my
controller that says, "Hey,
this is a time label, UILabel."
So, I'm going to make a
connection between my view
to my controller,
and to do that,
it's the same way you make
a connection using the segue
to create a segue.
Just hold down the control key
and drag over to your code.
And when I drop, what you'll see
is I'm creating a new outlet,
I can name it time
label, and connect it.
And when I do, what I get is I
get a property that's a UILabel
named time label.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So now in my controller,
anytime I want to access
that time label I
just use time label,
the time label property
to access it.
For the same thing, I want
to do with the pause button.
So I'm going to control-drag
in, call this Pause/Run button,
and now I have a UIButton
called Pause/Run button
that I can access.
The same thing when I
click the Pause button,
I want the Pause button to
change to a different image.
I also want the circle to
change to a different image.
So I can control-drag
from that image over here
and call this Pause/Run image.
So now I have a connection
to that UIImageView so that
when my action happens, I can
actually change that image.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Now, there's a couple other
properties that I need
that aren't specific to my demo,
and I've created the
code for it already.
And what I've done is
I've stored it down here
in the Code Snippet library.
So down here, we have--
I have demo properties.
Now, I've dragged
and drop to this code
into the Code Snippet library
given it some information,
and then anytime I want this
code I can just drag it right
out and drop it into
my document.
So, one of the other things I
want to do is we want to be able
to deal with the action of
hitting the pause button.
So we really need a method.
We need something where
we can make things happen
like change the Pause/Run
button, stop the timer
and change that circle.
So I'm going to make
a connection again
from the Pause button
down here and this time,
instead of an outlet, I'm going
to make an action connection
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
which will connect to a
method and I'm going to call
that method "Pause or Run".
Now, you'll see I have a
step for my new method.
And once again, I have
a pause or run method.
I have the code for
it, all ready to go.
So I'm just going to drag
that in and close the library.
Now, what this method
is doing is we're going
to determine whether or not
we need to set the image
to the pause button or that--
and the circle to the
timer running, or switch it
to the start button
and the timer stop.
Now it also calls a
method called update time
and we don't have that yet.
I'm going to add it in here.
One of the cool things
about Code Snippets is you
can give it a shortcut,
so I can just type in "Helpers"
and it'll add my code
right in there for me.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
It's great for like
reusable code
that you write all the
time and use all the time.
So, in update time, what we're
actually doing is setting the
time label, so that
property, we're using it
to update the time, and we're
getting that from time string
for interval which is up here
which really just a setting,
creating a formatted
string for us.
And in view will up here we're
determining whether we're going
to show the Pause or the Run
buttons when we load this view.
So, with any luck, I believe
we're done with this part
of the demo so let's try
it and see if it works.
So we're going to
run, filled in Run
and we should see those images
that were pre-populated.
We'll see that launch
image that shows up
and then we should see
our Welcome screen.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So launch image or
welcome screen.
And now as I click
on the timer button,
we'll see that the timer starts.
We click the Pause button
and because we have access
to those elements in our
user interface from our code,
we can change the buttons
based on the action
that happens from the user, OK?
So, let's stop this
and go back to slides.
One thing that I want
to be more specific
about is making outlets.
Now, I showed you how to
make an outlet from your view
to your code and create a
new property when you did it.
Now, you might already
have code that you want
to connect to your views.
And in this case, we have a
special keyword that we use
because in your user interface
when you're designing it,
you don't want all of your
properties to show up.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
You might have a lot of
properties in your project
and you don't need to see all
of them 'cause they're not
all relevant to your view.
So what we use is
the keyword IBOutlet
and what this says
is this is relevant
to my user interface
design and I want you
to show this property
when I'm designing.
I want to be able to
have access to it.
Now, the same thing is
happens with actions.
So with an action, this is
really just a connection
from your controls to your
methods and you'll have a lot
of methods in your
projects and not all
of them are relevant
to your views.
So what you're going to use is a
special keyword called IBAction,
and those actions are going to--
that's going to let Xcode know
that this is relevant
to your user interface.
So, with that, I would like
to invite Alex up to talk more
about what's next
with storyboards.
[applause]
>> Thank you Kelly.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Hello everyone.
So, Kelly gave us a good
introduction to how to set
up your project and do some
of the basic interactions
with interface builder.
But what do you need to do next?
Well, the interface is
really your first step
but there's a lot of ways
that those user interface
elements may want to interact
with your application
and you're going to need
to write some code to do that.
So I want to show you
some of that special code
that you're going to be writing
on a fairly regular basis.
To do that, I'm going
to add a couple
of views to our application.
First, I'm going to add a map
view and on that map view,
I'm going to put some route
information about your runs.
I'm then going to have a
segue to a detail view,
and importantly, I have some
data inside of my map view
and I want to pass that
data through the map view
and into the detail view.
And I'm going to show you how
you can take that little pocket
of data pass it through and
have the detail view show up.
So, what I want to
do is show you how
to use gesture recognizers,
this is how we're going
to do interactions from the map.
I want to show you how to
activate segues from code rather
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
than just from user
interface elements.
I'm going to talk
about how to pass data
from one view controller to
the next view controller.
I also want to talk about
two special connections
that many views have called
a delegate and a data source.
And finally, I want to show you
how to use reusable table cells
and how to add custom UI
elements to your application.
So, with that, let me
give you a quick demo.
So, unlike Kelly who was
starting off showing you how
to create an application
from scratch, I didn't want
to spend a lot of time up
here copying and pasting code
around just to get the
underlying behavior
that we desire.
So, I-- before the
demo, I wrote a number
of additional view controller
classes that we can use.
Now, I'm not going to show
you every method in those
but I'm going to show you some
of the more important methods
that you'll need to implement.
So to start off, let's
go to our storyboard
and here you'll see the
storyboard pretty much
where Kelly left it.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And the first thing I'm
going to do is set up so
that we can show the map.
So like Kelly did, I'll
use the object library,
filter down to the map view,
of course I'm getting
ahead of myself.
First I need to add
a view controller
to put the map view into.
So I'll drag that
out here and I'll go
to the identity inspector
as Kelly did up here
and I will set this to be a
map's route view controller.
Now, I can down to
my object library,
filter down to a
map, and add that in.
I also want to be able to
make a segue so I'm going
to control drag from my
routes button and I'm going
to add a push segue just like
Kelly did for the timer button.
Now you'll notice
when I did that,
it shrunk down my map
view, and with iOS 7,
I really want my map
view to be hinting
through the top navigation bar.
To do that, I'm going to
select the MyViewController,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
I'm going to go to its
properties, and over here,
you'll see that there's a
section called extend edges.
And on this case, I want
to be able to extend
under the top bars
and bottom bars.
And even though I don't
have bottom bars now,
if I were to add one, I'd
want to extend underneath it.
And you'll see now that my
map view extends all the way
up to the top of
the view controller.
Now, I need to make a couple
of connections and you saw
that I changed my
view controller
from a UIViewController to
our map route view controller.
So now I can just control
drag from my little mini doc
to my map view and I can
connect to the map view outlet.
But just as important of
that connection is I need
to make a connection from the
map view and drag down back
to my view controller.
In here, you'll see
that there's an outlet
on the map view called
the delegate.
So, what is a delegate?
A delegate for a user
interface item is an object
that can get special
notifications
from that user interface element
and it can also intervene
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
at special times for the
user interface element
and make decisions on how
data should be presented.
So, for example, a map
view can send notifications
when it's starting
to load map data
and when it's done
loading map data.
In our case, since we're
going to be adding overlays
to the map view, we want the map
view to tell us when it's ready
to receive those overlays.
And with that-- and we'll do
that via the delegate outlet.
So, at this point, we
could run the application,
tap the routes button
and we could see
that we'd load a map view.
But we want to do
a little bit more.
We want to be able to interact
with the map view as well.
And to do that, I'm going
to use a object called
the gesture recognizer.
A gesture recognizer is a way
that you can add
additional interaction
to controls especially controls
that don't necessarily
support the type
of interaction you
need to start with.
So on this case, I'm going to
drag a tap gesture recognizer
and drop it on to my map view.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
What this will allow me to
do is that when the user taps
into the map view, I'll be able
to take that tap and send it
to my view Vontroller.
And to do that, you'll see that
it added down here in my doc,
the tap gesture recognizer, I
can control drag between that
and my view controller,
and you'll see that one
of my sent actions I can
do is tap in map view.
So let's take a quick
look at some
of the code that backs this up.
[ Pause ]
So, the first method we have
here is a method you get
with every view controller.
Kelly showed at you briefly
when she created a
new view controller
and what is, is the ViewDidLoad.
ViewDidLoad is called
immediately
after the view controller
loads its interface
but before it's displayed
to the user.
Because of that,
it's a great place
where you can do
some initial set
up with your view controllers
before the user sees anything.
In this case, I'm actually going
to call the center
home region method
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
that I implemented earlier.
By default, the map would have
come up and displayed a map
of the entire world and
I'm certainly not that good
of a runner that I want to
see things on a global scale.
So, by calling this method,
I'll actually center the map
on the San Francisco Bay Area.
Likewise, I'm going to go ahead
and create my track overlays
here so that they'll be ready
when the map asks for them.
Next, you'll see that I
have my action method,
right here called
tap and map view.
This will be called by
the gesture recognizer
when the user touches
in to the map.
And you'll see here that
the first thing I'm going
to do is ask the
gesture recognizer
where in the view
the user touched.
I can then call a
method I wrote earlier
that will return the
correct map overlay for me
for that touch point,
and in this If block,
if I actually returned a route,
I'm going to go ahead and save
that selected route so I
can use it in just a moment.
And then I'm going
to call this method
performSegueWithIdentifier
runs for route.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Now, I haven't shown you
the segue yet, I'll show you
that in just a moment.
But the important thing
here is that you don't have
to initiates segues from just
other views in your higher
and your view controller.
You can in fact initiate a
segue whenever you need to
and you can get to that segue
by giving it an identifier.
So let's see how to
give it that identifier.
So I'm going to ahead and drag
out my next view controller
and it's giving me a
detail of view controller.
So it's common to have
detail views that are
in fact table views,
and like I did before,
I'm going to give
it a special class.
And now I want to create a segue
from my first my
map view controller
into my detail view
controller but because I'm going
to call this segue from my view
controller, Is'm actually going
to link from the view
controller to my next segue
and do my standard push
segment-- my push segue.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
But this time, I'm going
to select the segue,
I'm going to come up to
its attribute and I'm going
to give it an identifier
runs for route.
And now this segue
can be identified
from my view controller
as we saw.
Now, I'm not quite ready
to show you this running
because for the detail view
controller to be useful,
it needs to have some
information in it.
And so there's two things
we're going to need to do
to display that information.
First, we're going to need
to come to the table view
and we're going to select
the table view cell.
Now, I want to be able to
reuse the table view cell over
and over again and to do that,
I'm going to give it an
identifier called run summary.
And now for my code,
I'm going to be able
to populate multiple cells
using that identifier.
But let's go back first
for a moment and look
at the map routes
view controller.
You see this one more method
that's very important.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
This method is called
prepareForSegue.
prepareForSegue is a
method that is implemented
by every view controller and it
will be called whenever a view--
whenever a segue is about
to initiate an action
on the current view controller.
This is a great place
where you can then interact
with the segue.
You'll have both ends
of the connection.
The source-- the
source view controller
and the destination view
controller, and because of that,
I can pass information
from one view controller
into the next view controller.
And so you'll see here with the
code, I'm doing exactly that.
I check the segue
that's been invoked
and I checked its identifier
to see if it runs for route.
Now, in this example, I actually
only have one segue coming
out on my view controller.
So strictly speaking, I don't
need to check its identifier,
but it's good practice
to always do
so because you'll probably find
in many scenes, you're going
to add additional
segues and you don't what
to be crossing your
segues and finding
that you're performing
the wrong thing just
because you didn't check
the identifier of the segue.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
As I mentioned, the
segue has access
to the destination view
controller, in this case,
we know because of the segue
identifier that it's going
to be a route details
view controller.
And so I'm going to go
ahead and set the title
for the next view
controller and where we grab
that selection earlier when
these are tapped in the map,
we're going to go ahead
and set the route data
and the detail view controller
from the route data
in our selection.
And one last thing
I want to touch
on before we should
see this running is
that when I created the
detail view controller,
I created a table
view controller.
That table view controller
automatically gets a couple
of special connections.
First, it gets a delegate
connection, and in this case,
I don't actually need to
intervene in the table view
in anyway where I'll need
the delegate connection,
but it also gets a
data source connection.
The data source connection
is important to a number
of views because, you
know, for example,
a table view has no idea what
data you want to display in it.
So it's going to need
to ask some other object
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and in this case that would
be the view controller,
what data needs to be displayed.
Because I have a fairly
simple table view,
I just need to implement
two methods.
The first method is
number of rows in a section
and since I only have one
section, I know I just need
to return the route
data runs dot count.
Next, I need to implement
a method called tableView:
cellForRowAtIndexPath.
This is the actual method that
will provide table view cells
to the table view to be
displayed to the user interface.
And you'll see the first
method I call here is tableView
dequeueReusableCell
WithIdentifier.
And I asked for the
identifier run summary
and we saw it made that, I
selected my table view cell
and I gave it the
identifier run summary
and what the Table View is going
to do is it's going to say,
"Hey, do I already have a
cell named run summary?"
And if I don't, it's going--
I'll look in it a new one
and return that to me.
But it's only going to
do this for enough cells
to actually show what needs
to be displayed on screen.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
You can certainly imagine
having a Table View
with 10,000 rows in it.
I mean, who would want to
create 10,000 cells upfront,
be a horrible ways to
memory for something
that the user might
not even see.
And then, as you scroll
through the Table View,
as cells are scrolled
of the top,
they're put into the reuse
queue inside of the Table View
and those will be recycled
to show new data coming
in from the bottom.
So at this point, we
should have enough--
have done enough that we can go
ahead and run our application.
[ Pause ]
It'll launch, I can connect
the routes buttons now.
You'll see my map view
comes up and it's centered
on the San Francisco Bay Area
and I have a route highlighted.
If I go and tap on that
route, I go to a detail view
and here you see a detail
of when I run that route.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So, what else can we do?
Well, I told you that I
was going to show you how
to do some custom
content, and to do that,
I'm going to go ahead and
add one more view controller.
This time, I'm going to connect
a segue from the table view cell
because table view cells
can certainly invoke segues,
and I'm going to
do a push again.
Because I'm going to want
to pass some additional
information just like I did
in the map view controller
to the detai view controller,
I'm going to give this view
controller an identifier
as well called Run Details.
And just because
our designer did
such a great job
creating images for us,
I'm going to add an
image to this view.
But now, I'm going to come into
my object library and I'm going
to add just a UIView object.
Now, normally, just
adding a UIView
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
to your user interface
would be kind of boring.
Now, they are useful
as a great way
to collect other views together
by there's going to be times
when you're going to want
to do some custom display.
You're going to have
custom controls.
You're going to have
custom drawing.
You're going to show
special statuses to the user.
In this case, I want
to show a graph.
So just like we do
with view controllers,
I can go to the identity
inspector, expand it down,
and you'll see here that I have
an object called GraphView.
And I'm going to go ahead and
make this view a GraphView.
And so, when your
program is running
and this view is instantiated,
rather than instantiating
just a generic UIView,
it's going to know
to go on there
and instantiate a
GraphView object for me.
Now I'm not going to show you
the draw methods and things
like that, that's all
more UIKit information,
but I've already implemented
some background information
for this so we can
actually display something.
But of course I'm
going to want to come
down to my view controller
and drag a connection
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
up to the GraphView and it's
good I did that 'cause it shows
that I forgot to set
my custom class name
for my view controller and now
I can drag up to my GraphView
and I can make an
outlet to my GraphView.
And we'll use that just
like Kelly was doing
with her controls.
So now if I run again, I
can go to the routes again,
click through the map quickly,
and I can click on a detail
and here you see instead
of just a generic view,
I get this nice graph that was
designed by our designer again.
So with that, that's all
I've got to demo for you
and let's return to the slides.
So, what are some the important
methods that we talked about?
So, with the UIViewController,
a UIViewController is going
to be the base of every
scene in your storyboard.
So certainly it's a
very important object.
And every UIViewController has
a property called storyboard.
You can use storyboard
to access the storyboard
from which your view
controller was created.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
This is important because
you might want to go to--
you may want to skip a scene and
you could-- with this method,
you can ask the storyboard
for another scene via
identifier in your storyboard.
We also saw the importance
of the
performSegueWithIdentifier
method.
This allows you to pick out
a segue from your storyboard
and then have that
segue invoke its action
to its next view controller.
We showed a fairly
simple case of this
but you might do something
like build a generic menu,
and in that menu, you
can put segue identifiers
and then you could have a
bunch connections coming
up from your view controller
and you could invoke the
correct segue depending
on which menu button was
tapped on by the user.
And finally, we saw
the importance
of the prepareForSegue
command, our method.
This method allows us to-- or
is given to us by the segue
to notify us that it
is about to transition
to a new view controller
and it lets us
to do some additional
work such as past data
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
between view controllers.
So, what are some of the other
problems you might encounter
on storyboards?
Well, one, as you
build your application,
you'll find out that
you start off with kind
of a simple storyboard, and
as you work, it gets more,
and more, and more complicated.
Well, you might for
organizational purposes want
to break your storyboard up
into two or three storyboards.
In our case here, we
might actually want to--
instead of having one storyboard
doing both the timer path
and the routes path,
we could divide
that into two storyboards.
Not only does it make it
a little easier to scroll
around your storyboard, but
if you're using something
like version control, it
means one developer can work
on the timer path while
another developer works
on the route path, and if
they do separate check ins,
they are less likely to cause
conflicts in the source control.
There's another important
time when you might want
to use additional
storyboards as well.
For example, say you're doing--
we add social media
to our application.
And when we do that, we're
going to want some kind
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
of a login panel for the user.
But in our storyboard,
we don't want
to hang a login panel scene off
of every single scene
in the storyboard.
Our storyboard will
quickly get ridiculous.
So instead, I can
create a small storyboard
that implements a reusable
piece of logic, in this case,
a login panel and I can
call that from anywhere.
So, how do you create
a storyboard?
Well, there's a UIStoryboard
object
and it implements a few methods.
The important-- the first
important one is storyboard
with name.
This allows you to identify
a storyboard you'll save
and add it to your project.
The method-- the second
argument bundle and almost all
of your cases will be
your application bundle,
so you'll just pass an
NSBundle mainBundle.
And as I said, this will create
and return a storyboard object.
Once you have a storyboard
object,
you have a method
instantiateInitial
ViewController.
The initial view controller in
a storyboard is that that scene
that had the large
arrow pointing to it.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And so calling this method
means you'll create one
of those view controllers, load
its interface and display it.
But if you don't want to go
to the initial view controller
and in fact want to go to
a different view controller
in your storyboard
or different scene,
you can do
instantiateViewController
WithIdentifier.
So, a view controller just
like we did with our segues
and our table view cell
can be given an identifier
and this allows you
to jump right
to the view controller
without identifier.
For example, you might have--
and when doing a
login connection,
you may have too
slightly different scenes.
One might be for
doing an initial login
for a new user the first
time and another one might be
to just re-login the second time
you started the application.
This would allow you to use
one storyboard but start
from two different
points in the storyboard.
So, up to this point,
we've always been talking
about storyboard files.
And the storyboard
files are great
because they let
you see a large flow
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
of your application
in one place.
It really helps you visualize
how the user is going to move
to your application
and how data is going
to flow to the application.
But Interface Builder also
lets you edit what's called the
XIB File.
Now, in this case, I'm
showing an application--
an AppKit application rather
than an iOS Application
because if you're going to
do any AppKit development,
you're going to be using XIB
Files and not storyboards.
And in this case though,
I showed that you can store
much the similar objects.
For example, this shows you the
main menu of the application
as well as an app--
simple application window.
In XIB Files, you'll still
use view controllers.
You'll still make connections
from view controllers to windows
and views inside and connections
from the controls back
into the view controllers.
Except that you're going to
do a-- when you need to move,
say load a new window,
you'll actually explicitly
load a XIB file
like you would load
a second storyboard.
So, there's two last
objects that I want to talk
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
about real quick and these
objects are called NSNib
and UINib.
Now, you're probably going
to ask, what's nib file?
Everything we've talked about
has been a XIB or a storyboard.
Well, a XIB and storyboard
are actually just descriptions
of your interface and well they
are archive representations
of the objects, they're not
objects that are ready to load
like right in the
memory and start using.
Instead, when you
compile your application,
we compile the XIB Files and
storyboards into nib objects.
And in fact, when we
compile your storyboard,
rather than having to
load the entire storyboard
at launch time, we
compile the storyboard
into smaller nib files and
then as you've navigate
through your view controllers,
we'll instantiate those
individual nib files.
That way we don't have
to have everything
in memory again at one time.
And so, when is a place
where you might need to that?
Well, storyboards also use nibs
when you're using table views.
And as you do those--
load those prototypes,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
it's actually loading
the nib to load
that table view prototype
in for me.
But what if you wanted
to share table view cells
across multiple nibs?
Well, you could do that.
You can have a simple nib
and every time you wanted
to load those, you
could ask the nib, "Hey,
instantiate your objects
and then object return
would be a table view cell
and you could now take that
table view cell and register it
with a table view to be used
in a reusable fashion just
like we saw the storyboard do.
So with that, if you have
any more technical questions
about the information
that was presented here,
you can contact our
evangelist, Dave DeLong.
I also appointed you to a couple
of useful links here
in the documentation.
The first one is the human
interface guidelines.
If you're going to be developing
applications, you're going
to certainly want
to reference those,
and also to the interface
builder help documentation.
Some related sessions, if you
missed it, you're going to want
to watch the S code
core concepts video.
And very important
and very much related
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
to how interface builder
work is auto layout.
Now, Kelly and I didn't show
auto layout because in fact,
there's a full hour session on
how to use auto layout coming
up immediately after this.
So we'd like to invite you
to go upstairs to Presidio
and attend that session.
So, just to quickly
summarize, we showed you how
to create a simple project,
we showed you how to work
with storyboards, we showed
you how to make connections
to outlets and actions, we
showed you the importance
of delegates and data source
methods, we showed you how
to manually invoke segues,
and finally, we showed you how
to load storyboards and code.
With that, I'd like to
thank you for all attending.