TOMMY MACWILLIAM: Now that
we've written some Swift, let's write our first iOS app. Before we do, let's walk
through a few concepts that we'll need to
understand in order to do so. When we're writing an
iOS app, we're going to be mostly using a
framework called UIKit. So UIKit is a library that the folks
at Apple wrote and provided to us. And it has lots of different
classes, and methods, and functions that we're going to
use to create UI or user interface elements on the screen. So UIKit has different things like
tables, and images, and buttons, and basically all of the different UI
controls that you'd see in an iOS app, along with the ways to
transition among different views, perform animations, all that stuff. When we're writing iOS apps, we're going
to be following a pattern called MVC. And this stands for a
Model View Controller. And this is a general
software engineering pattern, but iOS uses it in particular. And what this pattern says
is you want to separate out your models, which are
how you model your data, so classes that represent just the
data that you're going to display. And models don't say anything
about how to display this data, or what this data looks like, or how
this data interacts with something. All they do is say here
is the data itself. The V in MVC stands for View. And you can think of the view as
basically the opposite of your data. The view says here is
some display of something, and it could be a bunch of different
data that's passed into a view. But I'm just going to translate
that into something that's actually displayed on the screen. Lastly, the C in MVC is Controller. iOS has this kind of funny convention
where they call them view controllers. And so MVVC is perhaps
more accurate, but you can think about the
controller as the bridge between your model and your view. So the controller might say,
I need to go fetch some data. I'll go fetch some data. I'll store that using my model, and then
I want to pass that model to some view so the view can display that data. So it's kind of
facilitating the interaction between the model and the view. So a lot of the code
that we write is mostly going to be at the controller layer. We're going to write some
simple models to represent data. And we'll write some
simple views, but iOS has so many built-in
views that we don't have to worry too much about that layer. So the first view that we're
going to take a look at is kind of the bread and butter of iOS
applications, which is the table view. So if you're using an app
like the Contacts app, where you're looking
at a list of contacts, that's what's called a table view. Even an app like Twitter, which is
sort of a list of tweets, that's using a table view probably under the hood. A table view is basically just a
list of anything, could be text, could be images. And this what's backing a
lot of interactions in iOS. And so that's why we're going to
take a look at this one first. When we open up our Xcode project, the
first thing we're going to need to do is create some views. And Xcode has this cool
feature called storyboards that are going to let us do that. So when I talk about
storyboards, well, that is is basically a drag and drop
container for all of your views. So in a storyboard, you can say
the app starts on this view. It has these buttons. When you click a button, it
transitions to this other view. And the storyboards are
what we're going to use to build out the UI layer for our app. We'll also talk about
outlets and actions. So this IB that's prefixed here,
it stands for Interface Builder. But outlets and actions
are basically a way for you to hook up controller methods or
controller fields to your view. So from a storyboard, you might hook
into an outlet in your controller that says, when I look
at this button element, here's the code that it corresponds to. So that's something
we'll see you in a bit. And then we'll also see segues. So a segue is a concept that allows
you to map some action on a UI element, so maybe a tap on a
row in our table view. When we want something
to happen, so when we want to transition to some other
view or transition to some other view controller, and we're going
to use segues to do that. So that's another concept
that we'll see shortly. So let's just jump right into it. So to get started, I'm
going to open up Xcode. And then I'm going to click
on Create a New Xcode project. Now this time, we want
to make sure that we've selected iOS over on the top left,
and then click on Single View App. Each of these other buttons will
create a different template for you, so basically start you off
with a different set of code. But we're just going to pick
the simplest template here, which is the single view app,
and then we'll click on Next. For our product name, this is
where we're going to name our app. So in this video, we're going
to be creating a Pokedex. So a Pokedex is an app that lists out
all of the Pokemon that there are. And when you tap on each one, you'll
see some more information about it. So for our product name, we're
going to type in Pokedex. Next, for team, we're going
to leave this at none. If you register with Apple,
you can create a team and publish apps to the App Store. That's where you'd select
whatever your Apple account is, but we're not worried
about that right now. So we'll just leave that as none. For the organization name, here
we're just going to put in CS50. Again, if you had an Apple account,
you would put in your organization name here, but we don't have one. And, similarly, for
organization identifier, we're just going to use this CS50 domain
backwards, just that common convention. But, again, if you had
an Apple account, here is where you would put that information. Next, for language, we want to make
sure that we've selected Swift. So Swift is the modern programming
language for creating apps. Objective-C is this older programming
language that still works. But we're going to be using Swift
throughout all of these videos, so make sure you've got that selected. And for user interface, make sure
that you've selected storyboard. Storyboard is basically a way that you
can create user interfaces by dragging and dropping various components. Swift UI is a brand new framework
that Apple just came out with, and it's basically a
different way of creating UIs. But we're going to go with storyboard. Lastly, you can leave all of
these other things unchecked. So core data is a way for you
to save data onto your device, and we'll take a look at how
you might do that a bit later. And unit tests and UI
tests are basically ways where you can
automatically test out your app. So you can write test to
make sure that your app is working as you'd expect it to, but
we're not worried about that right now. So we're just going to leave
those all unchecked as well. So now we can click
on Next, and Xcode is going to ask us where we'd
like to save the file. I'm just going to save
this to my desktop. You can see there's a checkbox down
here to create a Git repository. If you're familiar with Git,
feel free to leave that checked. And if not, you can
feel free to uncheck it. Doesn't really matter for
the purposes of this video whether or not you've checked it or not. So we can just leave it checked,
and then we can click on Create. OK, so now we can maximize Xcode and
check out the files that it's created. And to recap, we have on the left-hand
side here all of our different files. And so before Xcode just generated
that one main.swift file, this time it's generated
a whole lot more. So let's just start by
walking through each of these to make sure we understand
what we're doing. So the first file it generated
is called the app delegate. And you can think about this as
basically the main method for your app. So this is the class
that's going to be used when your app is woken
up from the background or started from the first time. It has a few methods in
here that we're not really going to worry about right now, but
let's just walk through them anyway. So the first thing we're doing
is we're saying import UIKit. You may recall that UIKit is
this framework and library that has all of these different methods
and things we're going to be using. Don't worry too much about
this UI application main. This is just saying that this
is sort of this main method or the entry point for our app. And then we have a bunch of syntax that
we should be familiar with already, but let's just sort of walk through it. So we're creating a new class. It's called AppDelegate. And this class is inheriting
from a couple of things. So these might be parent classes. These might be protocols. But, basically, because
they're following this colon, this is saying that we're
using this UI responder thing that Apple provided to us and
this UI application delegate thing that Apple provided to us. Our class has one field. It's called window. And the type of this window
is an optional UIWindow. So as you're starting to see,
many of the classes in UIKit are prefixed with this UI just sort
of indicating that it's from UIKit and has something to do
with the user interface. So this variable here, window,
has a type of UI window, but it might be nil because
we have this question mark. And it's also mutable, and it's
not initialized to anything. And then we just have a few methods
here that Xcode wrote out for us. None of the methods
actually do anything, but just to take a
look at the first one. So this method is called Application. It takes a few different arguments. The first one is UIApplication. And the second one is a dictionary
that maps some launch options key to anything. In Swift if you don't know
what the type of something is, you can just say any to sort of this
generic object that could be anything. And you notice here this question
mark means that it's optional. And all this method does is return true. You notice here that we're saying
it returns a Boolean value. So Xcode also wrote out a kind
of a bunch of nice comments here that explain what
these other methods do. Again, you can feel free
to read these comments, but they basically represent when your
app is going through different states like going into the background,
waking up in the background, being killed, stuff like that. And we're not going to need
to do any of that for our app, so we're probably not going
to open up this file again. The next file that Xcode generated
for us is called viewcontroller.swift. Again, we're going to import UIKit
to get all of those UI libraries. We're calling our class ViewController. And it's inheriting from
this UIViewController class. So this class provides us
with a bunch of base methods that we can override if we want to. And that's exactly what
Xcode is doing for us here. So we have this first
method called viewDidLoad. And we've overridden it. Though we haven't done anything
with that, but we can if we want to. So this viewDidLoad method is
going to be called automatically by iOS when this view loads. So we're saying this ViewController
was created for the first time, and you can use this to do some
setup or initialization, which we'll look at later. But for now, all we're
going to do is call this viewDidLoad on the superclass. So maybe inside of
UIViewController, there's some logic inside of viewDidLoad. It's good practice just to call
super.viewDidLoad in case there's anything in there that's really
important that we don't want to miss. So you'll see this as
another convention just making sure to call
the superclasses method inside of any method we override. And to do that, we just
use this super keyword. OK, so, next, we can
open up our storyboard. So now we finally see
an iPhone on the screen, but it doesn't have anything yet. But this is where we're going to
start adding different elements and buttons to our storyboard. If I come over here
to the left-hand side and expand this View
Controller scene, that's where going to start seeing
the elements that we add. So we'll come back to this. Just to quickly walk through
the other files Xcode generated, the first is this assets file. If you're adding images or something
like that to your application, you can put them inside
of this asset package. Next is another storyboard
representing the launch screen. So if you've opened up an app, which
you probably have, for the first time, you can show sort of that
initial loading screen before everything is loaded. A lot of apps have some simple
animation or something like that. This is where you'd put it is
inside of the launch screen. So your launch screen
isn't really interactive. It's usually just a
picture, or a color, or just something to display on the
iPhone while the app is loading up in the background. And, lastly, we have
this info.plist file. And you can think of this as
basically a configuration file. Again, Xcode has basically
generated everything we need to worry about already. So we're not going to modify this. But, for example, it's
saying that this launch screen storyboard file, that's the file
we should use for our splash screen. And the first storyboard that we
should open up when the app opens up is that main.storyboard. So that's sort of how that mapping is
happening inside of your application. But, again, we're not too worried
about this info.plist file right now. So let's start writing our app. So, oftentimes, I'd like to start
by writing the view and just sort of putting some
things on a storyboard to make sure I understand what type
of code I'm going to need to write. So we're going to start
off by starting over. So we're just going to delete
this initial view controller. And, instead, we're going to want to
add a special view controller called a Table View Controller. So up in the top right, you'll
see this little Home button. And when I click that, I get this
nice little autocomplete area where I can add objects to my storyboard. So the object that I'd like to
add is a Table View Controller. And a Table View Controller is
basically this nice utility class that's going to display
a table view for me and have all of the different methods
that I need to create that table view. So if I just start typing
table view, I'll see it here. Then I'm just going to click and drag
onto my storyboard, and there we go. So I have now a table view
inside of my storyboard. So let's go back to my
ViewController class. I know that this is going to
be a UI Table View Controller. So rather than inheriting from a
regular plane UI view controller, let's change this to be
a UITableViewController. So now I have this source file. I have this thing in my storyboard,
and I want to connect the two. I basically want to say that
this thing in my storyboard should correspond to this source file. So to do that, I'm going to
come back over to my storyboard. I'm going to make sure that I've
selected Table View Controller. And then I'm going to come over
here to the right-hand side. And I'm going to click this icon here. And the first thing here-- this
is called the identity inspector by the way. This first element on the right-
hand side here says Class. You notice that right now it's
just sort of this placeholder because we haven't really mapped
this thing in our storyboard to any of the classes
that we've written. So if I click on this dropdown, you see
I'm just going to get this one option. That's ViewController. So if I click that, then now we've
said that this item in the storyboard corresponds to this
ViewController class. And that's really
important or else Xcode is going to have no way of
mapping this UI to our controller. So one other thing that we have to
do is come over to this fourth tab here, which is the Attributes Inspector. And I'm going to scroll
down a bit, and I'm going to see this checkmark here
that says Is Initial View Controller. So before I deleted that other view
controller, this was actually checked. So I'm going to need to check it here. And this basically just tells
our application and Xcode that this is the part of the storyboard
that we should open up first. Right now it's sort of the only thing,
but we're going to add more later. And so we do need to tell Xcode that
this is the thing that you should open when you first open up the app. OK, so if you come back
over here and click on Run, I'm going to see my iOS simulator. And here is my table view. You'll see here that it's completely
empty because we haven't added anything to the cells yet, but it's a start. We finally put something on the screen. So now let's add some
data to our table view. To start, let's just declare an
array that contains a few Pokemon. I'm not going to write
out all 151 right now. But let's just get started
by writing out a simple list and then displaying
everything in that list. So the first thing I want to do is
to create a new class representing a single pokemon. So this is basically
the model for our app because it's going to contain
the data we want to display. So let's just create a new Swift file. It's just going to have
that one thin in it. So to come over here to the left-hand
side, click on this Pokedex folder. And then Control-Click,
and you'll see New File. So I'm going to click on that. And I'll get this kind of
familiar looking screen again. So this time I just want
to create a Swift file. And I'm going to click on Next. It's going to ask me what
I want to call that file. Let's call it Pokemon. And let's click Create. So there we go. Everything is blank save for
this sort of header comment. And so in this simple
version, let's just say that each pokemon just has a name
and a number, super, super simple. So let's create a struct. Let's call it Pokemon. And it's got two fields. It has a name. That's a string, and it's got a number. And that's an integer. So that's it. So this is basically the
model for application. It's really, really simple, just
a struct with the two fields. Now that we have that
model, let's use it. So I'm going to create a new
field on this class that's just a list of Pokemon. So to do that, we're
going to start with left. We're going to say Pokemon. We don't need to worry about
the type because the compiler is going to figure that out. And then inside of
this list, we're going to use this class that we just created. So here's my Pokemon. And you'll notice here
that when I hit open paren, I had this nice autocomplete complete
with the constructor already. Something that's nice
about structs in Swift is that the compiler
is automatically going to generate a constructor with
all of the required fields. So I have those two let fields, and
so Swift generated this constructor for me. Well, let's get to the first three. So Bulbasaur is 1. Ivysaur is 2. And Venusaur is 3. OK, pretty simple. Now we've just said that
there are three Pokemon here. We're my new class. So now let's use this data. We don't need to worry
about viewDidLoad, so we can just delete that. But UITableViewController has a few
different methods that if we override them are going to enable us to display
things in the table view controller. So the first method that we need to
override is called numberOfSections. So if I just start typing
number of sections, you've got this nice autocomplete. If I just hit Enter, I've got
all this stuff done for me. So this method is
called numberOfSections. Any table view in iOS can have sections. And within a section, it can have rows. For instance, in your contacts app,
there's sort of a section that says A, and there's a list of
people that start with A. And there's a B, list of
people who start with B. So our app is just
going to be a flat list. So we can just return 1. Say that we've got one section. That's it. Next, we want to specify how
many rows are in each section. So if I just start
typing number of rows, Xcode autocomplete saves me again. I'll get rid of this right-hand
side thing so it fits. And now we have this other method. And so now when we think
about how many rows do you want to have in
our tableView, well, you want to have one row for
each element in our model. So we're just going to return
pokemon with a lowercase p dot count. And this is just a simple
property on any list that says how many elements are in it. We saw that in our last example as well. So now in this runs, we
should have three rows. So the last thing we need to do
is to display the data in the row. So to do that, there's a
method we need to override called cellForRowAt indexPath. I'm going to hit Enter again,
generate a bunch of stuff for me. And now this is where we're actually
going to connect this data to our view. So you'll notice here that this
method returns a UITableViewCell. So, eventually, we're going to
need to return one of those. But before we do, let's take
a look at our storyboard again and just set some
properties on this row. So if I come over to the
storyboard, I'm going to click on where it
says Table View Cell. I can either click it here or here. It's the same thing. I'm going to open up
this right hand side. And I'm going to have
to specify a few things. So I'm over here in the tab,
which is the Attributes Inspector. And the first thing I'm
going to change is the style. So you can specify a
custom table view cell. You can add different
views to it if you want. Our cells are pretty simple
so we don't need to do that. So I'm just going to
set the style to basic. So once I do that, you'll see
that the storyboard changed. And now I have this text
field inside of the cell. And this is just because basic
is sort of a built-in cell style that can just display one line
of text, but that's all we need to do. So let's click on this again. Next, we're going to
fill in an identifier. So an identifier is basically
a string that distinguishes among different types of cells. So in our application, we just have
one table view, and all of the cells are the same. So they're all going to
have the same identifier. But you'd imagine if you had an app
with two or three different table views and each table view had
different types of cells, you'd need to specify different
identifiers to distinguish them. So let's just call our identifier--
let's just call it a PokemonCell because that's what it is. Nothing is going to change in
a storyboard when we do that. And the last thing I want to do
is add an accessory to the cell. So if I come over here to
Accessory, instead of none, I want to click on Disclosure Indicator. And what that did is that just added
a little arrow on the right-hand side of my cell, which is nice. And this is a little UI
element that indicates to the person using the app
that if you tap on this row, you're going to go to some other
thing to display more information. So that was kind of nice. We don't have to worry about drawing
an arrow or adding it for us. We can just use the built-in there. There's a bunch of other
properties here that you might want to play around
with like background or tint. You could sort of change
things like the size of cells. But this is it for now. We just want to display
text in each of our cells. So we're not going to do too much. So now if we were to
run the app again, it would still be blank because
we're not using any data. So let's not do that and,
instead, write our last method. So you'll see here that Xcode
is already being helpful. It's either helpful
or annoying depending on how you're feeling the day. It's saying that we need to
return a UITableViewCell. So let's do that. So we want to create a new variable. We'll call it cell. And we want to get something
that represents the current row. And so rather than constructing a
cell each time, what we want to do is instead use this pool of cells
that our app already has in memory. If we created a cell every
single time we needed one, our app would start using
a whole lot of memory. And often, we're not looking at too
many cells on the screen at once. If our table view is over
150 items, not all 150 are going to fit on the screen at once. And so it doesn't make sense to allocate
all 150 cells upfront if we're only displaying 10 of them or so. And so iOS this built-in
mechanism to do this for us. So there's going to be some
automatically created pool of cells. And what we're going to do is we're
going to say, I need a new cell. Just pull out of that cell-- pull out of that pool a new cell. Set some properties of that that I
want to display, and then return it. So to access this pool
is actually really easy. The first argument to this
function is called tableView. So I'm just going to say tableView dot. Again, I've got this
whole long list now. And I know that this method is
called-- it starts with dequeue. So I'm just going to start
typing the word dequeue. And I want this second one here,
dequeueReusableCell withIdentifier for IndexPath. So we'll go what all that
means, but let's just hit Enter. So the first argument to this
method is our identifier. And remember this is what we needed
to distinguish cells from each other. So this is where the
identifier comes into play. If this table view had
multiple different cell types, this is where you can specify I
want a cell of this identifier type. So we've only got one, so that's easy. And we called it pokemon cell. So that's the first argument. The second argument to this
function is our index path. So an index path is basically a pair
of integers for one representing the section the cell is in
and the second representing the row the section is in. So here we don't care about
section because we just said that there's one
section in the whole table. So we're not going to worry about that. We just care about the row. And so by specifying the row
into this dequeue cell method, we're basically making
sure that iOS doesn't reuse a cell that's already on the screen. Now you'd imagine that if
we're trying to display row 1 and it pulls from this pool of
cells, the cell that's currently being displayed at row 2, that's
going to be really bad because we're going to blow away row 2's contents. And so that doesn't make sense. Luckily, we don't need to
worry about any of this. iOS takes care of all of this for us. We just have to specify the
IndexPath that our cell is at. And so how do we know that? Well, it's simple. It's just passed into this function. We have this IndexPath parameter. So if I just say
IndexPath here, I'm done. So what I've just done is I've said
let's take a cell from this pool, and iOS manages allocating
everything for us, creates the cells, and destroys them as I need them. All I'm saying is just
give me a cell and I don't have to worry at all
about where that cell came from. And so this is really nice. So now that I have the cell,
ultimately, I want to return it. And that's going to make this little
compiler warning go away when I click Command-B. And sure enough, it's gone. But just grabbing a cell and then
returning it without doing anything isn't all that useful. And so what I want to
do is change the text of the cell to be the name
of the Pokemon for that row. So I'm going to say cell.textLabel. Again, autocomplete is
going to help me here. I didn't actually remember what it was. I remember it started with text. I just started typing
text and there we go. And then there's a property
on textLabel called text. And then I'm just going to
set that equal to my model. So here's my list of pokemon. I'm going to index into this
array based on my current row. So my current row-- again, I'm going
to use that indexPath variable, but this is struct that
contains a bunch of stuff. And we want to just
grab the row element. So this row is always
going to be between 0 and 2 because we know that there's
only three elements here, and we've specified that
by saying pokemon.count. But this is an object, and so we
just want to display the name. So name is a string, and
now our types make sense. And so there we go. We now have said with this cell that
you just gave, let's grab its textLabel, set its text to be the name of our
Pokemon, and then return that cell. You notice here that as
I was using autocomplete, Xcode added this little
question mark for me. And the reason being is that inside
of a UITableViewCell, this textLabel is actually optional
because in some cell types, it's not called a textLabel,
it's called something else. And so it could be nil. And so what this syntax does is
says if this variable is nil, just ignore this line. I just as easily could have
done if let, or guard let, or even put an exclamation point here. But this is just another sort of piece
of Swift syntax that's kind of nice. It just says, if this
is nil, don't crash. Just move on to the next line
and carry on with your life. So that's everything. Just to recap, we've
specified three things. We've said how many sections
does this table view have? How many rows are in each of those
sections, just the size of our list? And then what do we do with
each cell we want to display? Here we just grab a cell, change
its text, and then return the cell. So now let's run this. So let's come up here and
click the Play button. Our build succeeded, and there we go. We've got a list of three Pokemon. We've got these nice arrows
indicating if you tap them something should happen. We haven't done any of
that yet, so tapping it is just going to highlight it. But there is one thing
missing from this view that you've probably seen in a lot
of iOS apps, which is a title bar. If I were using an app and I needed
to go back, you usually a title bar at the back button, or
other controls, or a title. So let's add that to our app. So let's come back to
our main storyboard and come back to our
Table View Controller. So that title component in iOS is
called a Navigation Controller, which makes sense. The Navigation Controller
is basically this container that's going to enable you to navigate
among different view controllers. So if I click on View Controller and
then come up here to the Editor menu, if I scroll down a bit,
you're going to see Embed In. And then I've got a few options
here that's kind of cool. And so if I just click Embed In
Navigation Controller and click, here's what just happened. So Xcode created a new
navigation controller for me. And it put inside of it that
table view that I just added. Something else that
it did kind of nicely is that if I open up this
right-hand side and I click on Navigation Controller,
you'll see that it actually changed my initial view controller. It's saying that this
navigation controller, the sort of container
over my views, that's where my navigation should start. And now I have this title bar. This wasn't here before. If I double-click or if I just
click on this here and come over to the Attributes
Inspector on the right, this is called my Navigation Item. So Navigation Item contains a title. It has some text at the back
button, has some other stuff. But all we want to do
is give it a title. We'll just say Pokedex. And, now, if I come over
back to my storyboard, I've got this nice title
that wasn't there before. If I click Run, now my app has a
title and looks a bit more like what iOS table views typically look like. We have a navigation item up on top
with the title that we've specified and our table view. So now that we have
our table view working, we can see a screen where we have a
list of those Pokemon that we hardcoded. Next, let's look at how we
can create a second view controller to display more information
about each individual Pokemon. So to do that, let's start by
jumping back to my storyboard. So I want to add another view
controller to this storyboard. So I'm going to come up
here in the top right again, and I'm going to start
searching for a view controller. So this view won't be a table view. This will just be a
plain view controller, and we're going to add a
few of our own views to it. So I'm going to drag this
view controller over here. And now we can see I have a
second screen on my storyboard. So this view will just have a few
text fields to display information about the Pokemon. So let's come up to the top right
and add what's called a UI label. And this is pretty simple. It's just a view that
can display a string. So I'm going to drag this label
onto my second view controller. You can see these nice little alignment
lines will show me when it's centered. So let's open up this
panel to the right. Now let's change a few
things about this label. First, that font is
kind of small, so let me bump that up a bit let's say to 24. That looks pretty good. Let's make sure it's going to have
enough space for any Pokemon name, which might be long, so I'm just going
to drag this to the left and right. And you can see those alignment lines
again telling me when I'm centered. Lastly, let's come over here to
text alignment and just center this. So something else I like
to do with these views is to add in place holder data while
I'm designing the storyboard just so I can get a better sense of what the
view is actually going to look like. So I know that one of the
Pokemon's name is Bulbasaur, so I'll just try adding that. Underneath this, let's
have another UI label that's going to show the
number for each Pokemon. So once again, I'll come up here to
the top right, drag in another label. And let's make this font
a little bit bigger. And let's do the same thing. Let's increase the width
of this label a bit. Let's center the text. And then I want it to look like a pound
sign followed by a couple of zeros and then the number. So this is what our second view is going
to look like when all is said and done. After I've created
something in the storyboard. Now let's create a new
Swift file that can be the source for this view controller. So I'm going to come back
over here to the left, control-click on that Pokedex
folder, and click New File. So now I'm just going to
create a new Swift file, and we'll call this my
PokemonViewController. OK, so I have my new Swift file. So let's define a new
view controller class. So the first thing I want to do is
make sure I'm importing everything from UIKit since that's where all
of the UI elements are defined. And I'm going to say class
PokemonViewController. And this time I'm going to
inherit from UIViewController. Last time, remember, we inherited
from UITableViewController because we had a table view. This time we don't, so
we're just going to inherit from this plain UIViewController class. So the first thing I want to do is
create what's called an IBOutlet. And this is a way for me to
connect those labels I just added to my view controller
into my Swift source so that then I can manipulate them
from somewhere inside of this view controller. So to do that, I'm going to
create two fields in this class. I'm going to say @IBOutlet. We'll have it be mutable,
so we'll say var. And we'll call this
first one a nameLabel. And I'm just going to add
an exclamation point at-- I'm sorry. nameLabel,
UILabel, and then I'm just going to add an
exclamation point here so we don't have to worry about
whether or not this is nil. And then I'll add one
more for the number. So we'll call that numberLabel. And, again, we'll say UILabel here
with an exclamation mark at the end so we don't have to worry about
whether or not this is nil. And so you'll see here that Xcode
has these two little circles over here on the left indicating
that I can actually take these labels and connect them to somewhere
in my view controller. So let's go ahead and do that. We'll open back up the storyboard. And just as we did
last time, let's first set the class of this view controller. So I'm going to select the
View Controller on the left. Come over here to the right-hand side,
jump into the Identity Inspector. And under class, I'm going to
select my new PokemonViewController. So now my storyboard knows
that this view controller corresponds to that custom
class that I just created. Now to connect those two fields
we just created to the storyboard, we're going to come
over here on the left. We're going to hold
down control, and we're going to drag from
PokemonViewController over here. And you'll notice that my first
UILabel is now highlighted. So when I let go, you can see I have
this little menu showing me the outlets that I might want to connect. So I created that nameLabel outlet
before so I'm going to click on that. So now that name label is connected,
and let's connect our other label by control-click and drag
and selecting numberLabel. So now every time I reference that name
or numberLabel inside of that Swift file, I'm going to be able to
manipulate this view that I just added to my storyboard. To double check that everything
is correct and hooked up right, let's just select this first label. And on the right-hand
side, come all the way over to the last one here, which
is the Connections Inspector. Let's click on that, and you can
see I now have a referencing outlet. We're saying that this nameLabel is
inside of the PokemonViewController, and everything is hooked
up the way we'd expect. If I wanted to get rid of this, I
could just click on this little X, and it would disconnect the outlet. So now let's jump back to
our second view controller. So what we want to do is somehow get
some information from that first view controller and display it
here in the second one. So let's create a property for
some Pokemon object to display. So we'll say var pokemon. This time we don't say IBOutlet
because this doesn't correspond to a view in the view controller. Then the type is going to be that
Pokemon class we created before. So when our first view controller
creates the second view controller and transitions to it, we're going
to pass in this Pokemon information. So for now, let's just assume
that we have it already, and let's use it to change
what our view looks like. To do that, we're going to
use that viewDidLoad method. Remember that this is a
method that's automatically called by iOS when your view
controller has just finished loading. So this is a perfect method
to use because each time the view controller loads, we want
to change that text or that label to be equal to whatever the
Pokemon that we passed in. So we're going to say
override func viewDidLoad. Let autocomplete do that for us. Remember we're going to call super here. In case that viewDidLoad method
inside of UIViewController is doing something
important, we're just going to call super to make sure
that that still happens. And so now we can just set
the value of these two labels. So I can say nameLabel.text. That's just a property on that UILabel. And we'll set the name
equal to our Pokemon's name. That's easy. Now let's try the number label. We'll say numberLabel.text
equals pokemon.number. So let's try building this and make
sure that we don't have any problems. OK, so we do. So let's see what this error says. It says cannot assign value
type Int to type String. OK, that makes sense. If you remember that Pokemon struct,
we had number as an integer field. But text requires us to use a string. So all we have to do is
convert an integer to a string. In Swift, that's really easy. I can just say String, and that's just
going to wrap that integer in a string so we can actually display it. So this is basically the second
half of this interaction. Once we have a Pokemon and this
view controller is displayed, then we're going to display
the information we need. So now let's write the first
half of this interaction, which is how we're passing data from that
first view controller to the second. To do that, let's first
jump back to our storyboard. So you'll see that there's nothing
connecting these two views. So there's really no way for me to
get from this first view controller to this second view controller. To do that, we're going to
create what's called a segue. So a segue is just a way of defining
transitions between view controllers. So to create a segue, I'm going
to come over here to my cell on my first view controller. Again, I'm going to hold
down Control, and I'm going to drag over to this
second view controller. You'll notice again
that it's highlighted. And when I let go, I
get this menu saying there's a bunch of different
segues I can create. So I'm going to pick the
first, Selection Segue. This is just the simplest one. It's just going to show
that view controller. So I'll tap show. And now in my storyboard, you'll
see I have a segue defined between these two view controllers. So let's click on that segue. And just as we did with our cells, let's
give this segue a unique identifier. So we'll jump over here to
the Attributes Inspector. And, again, we have this identifier,
so let's call it our PokemonSegue. So now we're going to use that string
inside of our first view controller. So let's jump back there. And to use the segue,
we're going to override another method that's defined
on every UIViewController called prepare for segue. So I'll just start typing
that and let autocomplete fill in all of the details for me. So now let's think about what
we want this method to do. The first thing we want to do is make
sure we know what segue we're using. You can imagine in any
view controller you might have two or three different
segues to different view controllers depending on what button was pressed. In this case, we only
have one, but we're still going to use that
identifier to make sure that we're looking at the right thing. Then we want to get a reference
to this new second view controller and pass some data to it. So, first, let's use this
segue object that's passed in. It looks like the type
is a UI storyboard segue. And on that object there's a
property called identifier. So remember we called our
identifier our PokemonSegue. So let's just make sure that
we're always using that. Next, we want to get the destination
view controller that we're moving to. Luckily, segue has a
property called destination. But you'll notice from this autocomplete
that the type of destination is a regular UIViewController. And that makes sense
because you're going to be moving among UIViewControllers. But we want to make sure
that we're accessing this as a PokemonViewController. The reason being is we defined
that field called Pokemon, and we need to use that
field to pass in data. But not every UIViewController
has a field called Pokemon. So what we need to do is cast
this destination UIViewController into an instance of a
PokemonViewController. And so we're going to use
some Swift syntax to do that. It's very similar to that
optional syntax we saw before. We're going to say if left destination
equals segue.destination as followed by a question mark and
then the name of our class, which is a PokemonViewController. So here this is really similar
to that optional syntax. This is going to say if this
segue.destination, if it can't be cast to a PokemonViewController,
if it's of another type, then this is just going to
return nil, and we're never going to enter this block. But if it can be cast
and we expect that it can because we know what type
we put in the storyboard, then now this destination variable is
of type PokemonViewController. And that's great because now
we can say destination.pokemon. And now we can pass along whatever
pokemon corresponds to the row the user just selected. So to get that row, there's
a property on table view called selected index path for row. So let's use that. We're going to index into
our Pokemon array using tableView.indexPathForSelectedRow. And you'll notice that
this isn't an optional, so let's just put an
exclamation point here because we know that some row
must be selected in order for us to be in this segue method. And, again, remember this index
path has both a row and a section, but we only care about the row. So we're just going to say dot row. OK, so what we've done here is
we've indexed into that list, getting the item that corresponds
to the row the user just selected. And now we're passing that
to our new view controller. You'll notice that we
didn't have to instantiate that view controller ourselves. There was no creating that object. That's something that iOS does
for us, and all we need to do is manipulate the segue
to change the data that's used in that view controller. So let's try running this
app and see what happens. OK just like before, I
have my list of Pokemon. Last time when I tapped them nothing
happened, but let's try doing that now. OK, so it looks like we've
just pushed our second view controller onto the stack, and
we've passed along the information we were trying to pass along. If I tap Venusaur instead,
you'll notice that this data is being transferred back and forth
between these view controllers. But there's one last thing that's wrong. Remember in my story board I
wanted to format this number with a hash sign
followed by leading zeros to make sure I always
had a three-digit number. So let's look at how we
might want to do that. Let's jump back to our
PokemonViewController. And rather than just
wrapping this Int in a String and just taking that
number straight away, let's use a method on the
string class called format. And format is going to be exactly the
same as printf that we saw earlier. We're going to define
some format string. And then we can pass arguments
to format so that we can insert those values into the string. So we're going to say String
format, and the first argument here is going to be our format String. So let's start with a hash. And then remember in printf If I want
to pad a number with leading zeros, I can say %03 if I want this to be a
total of three digits followed by d because I'm passing it an integer. And then, finally, let's just
pass in that Pokemon number. So now let's run our app again. Let's tap on Venusaur. And now this is what we
wanted our data to look like. Let's tap on one more just to be sure,
and everything looks like it's working. So now we have two view controllers. They're able to pass data
back and forth to each other so that we can display more details
about something in our table view. Now, in our next video,
we'll take a look at how to load this data dynamically
from somewhere on the internet rather than just hard coding this list.