[ Silence ]
>> All right.
All right, we're back.
This is Computer Science S76.
So there weren't too many questions from you,
so that means it's my turn to start asking questions.
Last week we started talking about MVC, which,
how about we'll start with the softball, stands for what?
>> Model-view-controller.
Okay. So what is the Controller in that acronym?
>> [Inaudible response].
.
>> Okay. Brains of the application, so it's the code
that you write, the so-called business logic
that governs the control of your application.
It's the entry point to really the logic that you write.
All right?
How about the V, view?
>> Interactions with the user.
>> Yeah, so interactions with the user.
So view typically deals with presentation,
both the anesthetics thereof,
so how you're displaying information to the user,
and then it typically has some UI mechanisms, like buttons
and text fields and whatnot, that somehow send messages back
to which of the letters?
>> The Controller.
So you have this bidirectional arrow essentially between your C
and your V, so the two are talking,
but you do not have an arrow between, say, V and M directly.
Rather the model is where you typically represent your data,
and we'll do a simple example tonight of what you might want
to model with its own class that we write ourselves.
But typically, all of those communications should be
marshaled through the so-called Controller,
so that's where really the intellectual property
of your app tends to be, in the aesthetics or in the View.
And then the model is where we'll do our data typing
and our data representation encapsulation.
We'll do a bit of that in just a bit.
All right.
So that was MVC, and in what --
what form does this take in the world of iOS?
Well, in iOS, we have a few classes with the UI kit,
so this is the API that provides access
to UI related things in iOS.
And UIApplication was a class that we barely spent any time
with because we just make reference to it in Main,
essentially, where we have a new UIApplication,
and that's the class
that embodies your actual application.
But beyond that, we don't really need to care too much about it,
but UIApplicationDelegate is a class
that we spent a little more time talking about,
and what is that class's role when you create an iOS app?
Use it in a sentence that makes it sound
like technically you're comfy with what its role is.
>> Isn't that where you put your code?
>> So it's where you put your code,
or at least the first entry point.
You wouldn't put your code in Main.M,
but rather you might first put it in UIApplicationDelegate,
and conceptually it's to this class, or an object thereof,
that controlled your application is delegated or passed.
So he's now the guy in charge.
But as soon as we started doing more interesting applications
than just rectangles on the screen
and started getting interactions from users,
we further delegated control from the UIApplicationDelegate
to an object of what type?
>> UIViewController.
And we don't have to, per se.
Games don't necessarily use that same class,
and custom applications don't necessarily use that class,
but the UIViewController's nice because it comes
with a whole bunch of built in functionality
for handling various common paradigms, like buttons
and sliding and tabular views and so forth.
So it's a common starting point, certainly for the types
of menued applications we've looked at thus far.
And the UIViewController in turn makes you solve bunches
of UIView objects, but typically not just generic UIView objects,
but typically not just generic UIView objects.
What are some subclasses that we've used and talked about?
Two of which I've enumerated tonight, albeit off camera.
Starts with UI, ends with utton.
>> UI Buttons.
>> Okay, so UI Buttons [laughter].
So this was just a subclass,
and thus far we've essentially used these things
by dragging and dropping.
But we did have a quick glimpse last time
at no Nib.Xcode project, which was a reimplementation
of that super simple app that gave me a text field
for my name, gave me a button with --
to click on to actually then trigger a UIAlertView saying
hello David, or hello such and such.
And we dragged and dropped that UI Button,
but UI Button is just a specific incarnation of UIView,
and if you think back to Xcode and think back
to Interface Builder, that drag and drop interface,
what we're essentially doing by dragging
and dropping is dropping these little objects on top
of a canvas, and they can overlay, overlay, overlay.
And we'll do a little more of that
in a different sense tonight by actually responding
to arbitrary key presses, or pinches, for zooms and the like,
so we can actually listen to the entire U View --
UIView, as we will see.
UIWindow finally was a special case of a UIView.
It has some additional stuff baked into it
that essentially describes the full rectangular area
of the iOS device in question.
But today we'll spend a bit more time in UIViewController
and UIView, but we'll see those other classes again along
the way.
So let's see.
So last time, we looked at a whole bunch of these templates.
None of these templates are strictly necessary.
You could just start with nothing in your project
and start writing files by hand.
The problem is you just end up reinventing the wheel.
There's a lot of configuration details that we saw in the form
of Property Lists, those key value pairs
that would just be a pain to do manually.
So Xcode helps jumpstart things either
with an empty application,
which has the bare minimum of configuration.
And then we looked at Single View last time and then a lot
of you looked at Utility View and you're knee-deep
in a Utility View application for Evil Hangman.
So if we proceed a little further today, let's take a look
at these two last ones, not because they in
and of themselves are applications you'll need to use
for the project, but rather because they're illustrative
of somewhat more complex applications
that you might implement that nonetheless assume familiarity
with the overall structure we had earlier.
So let's do this.
First, let's start somewhere simple.
I'm going to go into Xcode, and I'm going to first start,
not with an empty application, which was super uninteresting
by the end of last week, but Single View Application,
and then we'll quickly build on from there.
I'm going to go ahead and call this Single View.
I'm going to just store it on my desktop.
I'm going to uncheck Storyboards here, click next,
and then I'm going to go ahead and click okay.
And now we have the following boilerplate files.
So suppose by contrast I didn't just create this right in front
of you, but you were handed this project from someone else,
and you want to wrap your mind
as to what's going on inside of it.
Where's the best place to start
to understand what you've been handed?
>> A .H file.
ViewController.H.
>> Okay. ViewController.H. I would propose that's maybe a
little too deep at first glance.
Why don't we start where the beginning of the story begins?
>> AppDelegate [inaudible]?
>> Yeah, AppDelegate, and really if we want to be super anal
about this, technically it's Main.M
that kick starts the whole process,
and a quick glance should at least reassure
that there's nothing special, nothing different there.
But indeed it's in this file that we see mention,
not only of UIApplication, but also AppDelegate,
to whom we're going to delegate control.
So we've confirmed that there's nothing distinct in there.
So now I would propose among the AppDelegate files,
starting with the .H is probably the better place,
because it gives you, in theory, an overview of what's
about to go on, and it also gives you a sense of what needs
to be implemented in the .M file.
So what's going on here?
Well, a quick recap.
The import line does what for us?
>> It imports the user interface kit.
>> Okay, good.
It imports the user interface kit.
And what does that mean?
So in that .H file, there's a whole bunch
of class declarations, perhaps, maybe a bunch
of constants that are defined.
A whole bunch of things that we want to take for granted exist,
and this is our way of teaching Xcode that we want
to use the code that someone else wrote.
All right, on the next line we have at Class ViewController.
Actually, that's a little strange.
There's a semicolon, yet no implementation of the class.
What is it with this line here, at Class ViewController,
which we've not really spent time on?
Yeah.
>> So the at Class actually tells it that it's [inaudible],
but doesn't actually import it.
>> Exactly.
>> Unless you were going to use one of its methods,
that should suffice to tell it that it exists.
>> Exactly.
So we didn't spend time on this last time,
but this is what's called a forward declaration.
It's a little hint to the compiler saying there is going
to be a class called ViewController.
I'm not going to tell you anything more about it,
but if you see mentions of ViewController elsewhere
in this file, don't complain.
Don't give me any red warning saying that's no --
that not allowed.
This is just teaching the compiler what's actually going
to come, and indeed where are we using that?
Well, a few lines later we're declaring a property whose
purpose in life is to store a pointer
to a ViewController object.
So this is, long story short,
in way of avoiding potential circular references whereby one
file might import another, might import another.
A common paradigm is if you only need to make mention
of the class in this way in your .H file,
just to use a forward declaration and not
to import the whole ViewController.H file,
for instance.
Okay, what's this third, more interesting line saying?
At Interface AppDelegate colon UIResponder angled
brackets UIApplicationDelegate.
Let's start easily.
This just declares what?
What's this mention in black of AppDelegate?
>> Name of the class.
>> Name of the class, all right?
The colon UIResponder means?
>> [Inaudible audience response].
>> It's the -- UIResponder is the parent of the class,
so AppDelegate is going to descend
from UIResponder, and someone else?
The UIApplicationDelegate in angled brackets?
>> It's a protocol.
>> It's a protocol, so we're saying that we're going
to implement the UIApplicationDelegate protocol,
and this makes sense because the class, after all,
is called AppDelegate.
All right?
What are the two properties?
Well, we saw one ViewController.
We have another pointer to the UIWindow that'll give us access
to the full rectangular portion of the screen, and that's it.
All right?
So now let's dive into the M file.
All of that is boilerplate.
None of that is different from what we saw last week.
This file's always a little overwhelming at first glance
when you have all of these comments,
but that just means they're not really doing anything.
So let's ignore anything that's not actually doing anything
functional, and focus only on this first method up top named,
what's the name of this method that remains?
>> AppDelegate?
>> Not AppDelegate, so that's the -- that's the class name.
The name of the method is?
>> didFinishLaunchingWithOptions.
>> Yeah, application didFinishLaunchingWithOptions,
so longly named method there, but what's this doing?
So first, it's allocating a window.
It's initializing it with a frame that's just referring
to the rectangle, if we keep describing it.
ViewController gets -- so here is
where we're effectively configuring our AppDelegate
with another guy to whom we're going
to delegate control, the ViewController.
Self.ViewController is a property that's built
into the AppDelegate class, so if you actually look
up the documentation for a UIApplicationDelegate,
you'll see that it comes with that property,
so we're setting it in that way.
Finally we're setting the -- sorry.
This is our property that we declared in the .H file,
but it comes with a RootViewController property
in the window, that's in the UIWindow documentation.
And then that second to last line, Make Key Invisible,
just gives control
to the ViewIController to the foreground.
What else does this application do?
Anything? So that's it.
All we have is the Nib where we could start
to put our user interface, but beyond that,
this application does terribly, terribly little.
So let's try to see -- first, any questions?
So let's take a more complex tour and see
if we can't now understand a new application entirely,
but this time while thinking about it in the context
of applications we've seen thus far.
So among tonight's source code is a folder called
Master Detail.
This is essentially a simplified version of the standard template
that comes with Xcode, so all I did was tidy things up
and remove things that didn't need to be there.
As usual, let's go into our Main.M file.
Let me close some superfluous windows over there.
Nothing new happening here,
so that's the same file we saw earlier.
What file should we probably dive
into next following the same rule of thumb?
>> AppDelegate.
>> Okay, so AppDelegate.
Start with the .H. That looks perfectly the same,
so nothing new there.
AppDelegate.M, so here we have what seems to be the same code
as before, except for -- any differences?
>> MasterViewController.
>> So we're instantiating a MasterViewController.
So that's interesting.
It's not just a ViewController, it's a MasterViewController,
and we're making it the RootViewController, so to speak.
So most of this code is the same,
but I'm instantiating a different class name,
but that's because someone at Apple decided for this template
that we're not going to have one ViewController implemented
for you in .H and .M. We're going to have what appears
to be two: Master ViewController and Detail ViewController.
So at this point I'm a little puzzled
as to what this thing's going to do, so let me go ahead
and just run the application,
and see if we can't then work backwards
as to how the behavior we're about to see is functioning.
So let me go ahead and foreground the simulator,
and in just a moment, we'll see it pop to the foreground.
Lately the simulator has been loading a little slowly,
but there we have it.
And now we have, interesting, an application
that has nothing going on here.
You can just about see the horizontal lines,
so this is some kind of tabular view going on,
and this application, the starting point, is designed just
to do something stupid, just
to insert a new row every time you click the plus.
And it's choosing the timestamp in UTC, so universal --
universal time, and adding a row accordingly.
So if I do that ad nauseum, we'll just get lots of lots
of rows, but you might recall this paradigm in iOS.
If I click edit, I get this familiar UI.
I can go ahead and delete, say, that one,
by clicking that circle, then clicking the delete button.
Then I say done, and so there we have that functionality.
And if I click a row itself, Detail View Content Goes Here.
So what's just happened apparently is
that we've made some kind of transition
from the Master ViewController
to what they call the Detail ViewController,
so this is illustrative now of how you can hand off control
between two ViewControllers.
Recall that you've essentially been doing this
in the utility application, or you will soon be doing this
in the utility application for Evil Hangman,
but you were choosing a different type
of transition Rather than side to side,
you were doing front to back flipping.
So this one still is a little different in its implementation.
Let's next go into, from AppDelegate.M,
let's start with Master ViewController.H. Is there
anything of interest in here?
So Master ViewController has a property that's going
to store the address of what kind of object?
Looks like a Detail ViewController..
So if you think about this high level,
the RootViewController's the Master ViewController.
He apparently is somehow going to have attached
to him the address of a Detail ViewController,
so it seems to be the case, indeed,
that the Master ViewController is in charge.
Now we haven't done any of that wiring yet,
so let's go into the .M file for Master ViewController,
get the lay of the land, this is a little overwhelming
but we'll get there.
So now let me scroll back up to the top
and see what's interesting here.
So let's focus first on one of these at a time.
So here's a method called In It With Nib Name.
This has typically been called automatically for us,
because we've had a bunch of starting points
in our applications thus far in class
where we had those .XID files.
Somehow they were wired up to my code and loaded automatically,
and we just initialized them based on the XML file
that is the .XID file somewhere on my hard drive.
But now we're explicitly implementing in In It
With Nib Name bundle method, and if I hover over this thing
and check the question mark,
notice that there's a whole bunch of documentation in here
and this method appears to come
from an ancestor class known as UIViewController.
So if we really look underneath the hood,
Master ViewController descends from a new class
that gives us the tabular View, UITableViewController,
which in turn descends from the thing we've seen
in applications thus far, UIViewController.
So long story short, if I actually start
to read this documentation, this will explain how the In It
With Nib Name bundle method works,
and it is the guy that's responsible for loading
from the hard drive that .XID file, and somehow making all
of the connections we discussed last weekend in lab.
So it's doing one additional thing though.
It's calling first the superclasses implementation
of that same method, In It With Nib Name bundle.
So that's been called automatically for us,
because we have not explicitly implemented this method thus
far, but it's also doing what, in high-level terms apparently?
What does it appear to be doing?
You seem to have a guess in mind.
Oh yes, yeah.
>> [Inaudible] initializes the [inaudible] class.
>> Initializes the -- oh, the first line does, yes.
Sorry. Let me change my highlighting.
So it's not commented, but was it --
what do these three lines seem to be doing?
>> Setting the title.
>> Yeah, setting the title of self, so self.title.
What is self?
What type of object is self at this point in time?
>> Master ViewController.
>> So it's a Master ViewController,
which in turn is a UITableViewController,
which in turn is a UIViewController,
so if we really started poking around the docs,
we would probably see
that UIViewController's have a property called?
>> Title.
>> Title. And indeed, that's where this is coming from,
our UITableViewControllers.
And if we go back to the application that was running,
notice when we're here, it's the title master,
that's where they came from.
So we could have typed this in manually into the Nib,
but because we created the ViewController N code,
we don't actually have to do that there.
Alright so this, as an aside, is a common paradigm.
Anytime you modify self, it's common to call
to check is self -- if self is non-null,
so that is if everything went okay
and the previous line did not return nil,
meaning there's some memory error or the like,
you check first that self exists okay before touching one
of its properties as we did here with self.title.
All right.
So next, I think we saw this last time.
View Did Load.
We saw this in our no Nib example, I believe.
View Did Load, if we read the documentation,
is just a method that's called
when the View Did Load, so aptly named.
And what does this guy seem to be doing?
It's wrapping a bit, but it's about four lines of code total.
>> It's adding the edit button.
>> Yeah, it seems to be adding the edit button.
So first we called the parents a met version of the method,
and if we read the documentation,
we will be reminded typically,
be sure to call the parent before you do your own thing.
Self.Navigation.Left Button Bar Item, I don't really know
where this comes from, but I can probably guess
that because we're implementing a subclass
of the UITableViewController,
presumably a UITableView has a property called navigation item.
And that navigation item refers to the little blue or gray bar
at the top of this kind of application,
and .Left Button Item refers to -- .Left Bar Button Item,
refers to the thing at top left,
and we seem to be storing what there?
Self.Edit Button Type Item, whatever that happens to be,
and then UI Button Item, add button, so if we read this,
we're apparently instantiating a UI Bar Button Item,
allocating it, initializing it with this thing,
UI Bar Button System Add.
So there's a lot of code there that's not all that interesting
to dwell on now, but if you think back to what's going on,
this is really just the code version of going to something
like my Nib, opening up the toolbar over here,
scrolling down to the objects down here, and if we scroll,
scroll, scroll, scroll, we'll eventually find Navigation Bar
and Navigation Item, so what I'm doing, a code is the equivalent
of dragging and dropping this into the user interface,
much like we were doing last week.
So that's -- that's all.
The magic that we've been taking for granted of dragging
and dropping is now being implemented more lower level
in code.
All right.
So let's not worry too much about the user interface
because that's not all that interesting
at the end of the day.
Let me just point out a few
of the additional methods we've implemented.
These are methods that we've implemented because we need
to implement table related functionality.
One of these is super simple.
The method called Number Of Sections In TableView,
if you read the documentation, its purpose in life is
to return a number, namely how many rows should there be
in the table, so that the operating system knows
when to stop rendering rows.
So in this case, we've just returned -- sorry.
Not rows, sections.
So sections are groupings of rows together,
and if you have an iPhone and you go to your settings menu,
you'll see that there are rows in your settings menu,
but they're typically clustered with some kind of bold header.
That's referring to a section.
We had no such aesthetics here,
so we just have one massive section, so I've hardcoded --
may have hardcoded the value of one in this template.
So Next, TableView, Number Of Rows In Section.
So this is the method that tells the program how many rows are --
should actually be in that table,
how many dates have been added to the table.
But what is Underscore Objects.Count?
Where did that come from?
>> It probably holds the information for the rows.
>> Yeah, it probably holds the information for the rows
because again, think about -- recall the difference between C
and V, Controller and View.
The View may very well render what looks like a table,
but if there's any data that you're rendering,
it's the Controller's job in life to actually keep track
of that and just pass it to the View.
So we shouldn't be storing those dates in the View per se.
We should be storing all of those dates after every click
of the plus button somewhere inside of my Controller,
and then just handing it to the View.
So Underscore Objects, if we glance back at the top
of the file, was actually declared up here,
and I've declared an NS mutable array.
What's the difference between mutable array and NS array?
>> You can modify it?
>> You can modify it.
So it's mutable in that you can change it.
You can add, remove to and from it.
So I've done At Interface Master ViewController open paren,
closed paren, so again, we've already did that, I thought.
In the .H file, we had
At Interface MasterViewController open
curly brace.
Why have we repeated ourselves and added these parentheses?
>> For it to be private?
>> For it to be private or to the illusion of privacy.
So we've used an unnamed category here,
so recall that categories are just ways
of grouping related functions.
But the world, as a convention, has adopted it as a means
of approximating the idea of private methods
and private data members, private only in the sense
that they are not being declared to the world in the .H file,
because .H files can be imported by other people,
which means other people would see our implementation details.
But they're nonetheless adding it
to the class Master ViewController,
because it's inside of this declaration.
So we apparently have an NS mutable array Underscore
Objects, but where is that guy first used?
Well, let me scroll down, and scroll down, and scroll down,
and it looks like, let's see, where's our Underscore Objects?
>> [Inaudible audience response].
>> Ah, there we go.
Exactly. So here we have a method.
Insert New Object colon.
So what do you think is inducing this method to be called,
based on what we've seen thus far?
>> [Inaudible] the plus button?
>> So pitting the plus button, and how was that done?
Was it done in Interface Builder, or...
So insert new object.
So again, let's -- let's just do a little highlight and copy.
Let's see where it -- oh, interesting.
So View Did Load.
We didn't finish that story.
We didn't -- we -- Apple did not use Interface Builder teams
to wire things up.
They didn't -- done it all in low-level code,
so in View Did Load, we started telling that story in terms
of the Left Button Bar Item.
If we go a little deeper, notice what's happening here.
When we declared this UI Bar Button Item and allocate it
and initialize it, we're choosing -- this is a constant,
this very long word UI Bar Button System Item Add,
is just the atrociously named constant for the plus icon.
That's all that's doing.
It's aesthetic.
But we're saying Target colon Self Action
at Selector Insert New Object.
So first of all, what does Action colon
at Selector Insert New Object doing functionally?
>> It's just a message that should be sent
when it's -- the action happens.
>> Exactly.
When some action happens, which in this case is going
to be the touching of the button,
that's the default behavior for one of these buttons
when it's clicked by a user's finger,
what message do you want to send to an object?
You want to send this message: Insert New Object.
Put another way, what method do you want to call.
And to which object will that message be passed?
On which object will that method be called?
>> The target.
>> The targets.
So Target colon Self means this class, this object,
and that is why slightly more lower
in the screen we have an implementation
of the method that we want to call.
So as an aside, the reason that we have this funky syntax,
at Selector open paren closed paren,
is so that it's clear what the name of the message is
that you want to send, because we've seen methods
that have colons in them.
And it would just get very complicated,
if not impossible, to parse the string.
If you had Action colon Insert New Object colon, where --
which colon belongs to what?
So that's the idea of At Selector.
It's just a syntactic thing.
So that means when you click that plus button,
this guy is actually called so, in answer to the question,
where is the objects NS mutable array coming from?
We instantiate it lazily.
The first time we need it, we check does it exist?
If it doesn't exist, that is if Underscore Objects equals nil,
we're going to go ahead and instantiate an NS mutable array
and then we're going to start populating it.
And at this point, if you start to read through the code,
you'll see a couple new features.
There's this notion of the Index Path,
which is something specific to these UI Table Views.
A path is just a couple of numbers, two numbers together.
A section and a row.
So an index path is just an object
that contains those two values, and if you keep reading further
in the code, you'll see that this is the function
that actually does the generation of an insertion
of the date into that actual Table View.
Yeah.
>> First of all, say we have a property
for the objects variable.
What would be -- would be cost if you used the alternative?
[Inaudible]?
>> Good question.
So suppose we had declared objects as a property.
There would be a couple of implications.
One, we could do Self.Objects and mutate it that way.
On the other hand, so could anyone else who happens
to be importing, for instance, my.H file,
if we declared the property there,
but we don't have to declare there.
You would get some marginally additional functionality
because by default, the setter and/or the getter will often
have additional code in them.
For instance, if you've declared it to be atomic,
it will have some additional code with the setter.
The setter will, by default,
make sure that you never set an object equal to itself,
which can do some bad things circularly.
So you would get some protections,
but you pay a price.
What's the downside?
Do you -- would you conjecture of using a property
to implement this container as opposed
to just declaring a raw pointer like this?
>> It takes longer?
>> It takes longer.
And we're talking, you know, a negligible amount of time
for something like this where clearly, I,
the human in the bottleneck for any slowness
in this application, how quickly I can press, but in theory,
that's why they've done it in this way.
Just to -- we're the only ones using the property.
Not the rest of the world.
I know how to use it, I just don't need the marginal overhead
of a setter and a getter.
But a good question.
Okay. So let's not spend too much time on the particulars
of this specific application, but let's just scroll
through lastly the other methods that might be here.
So there's this one, TableView, Self or Row at Index Path,
because this one method actually reveals an interesting design
pattern that's not uncommon,
especially for performance reasons.
So TableView, Self or Row At Index Path,
and then it's given an index path.
The purpose in life of this method,
if we read the documentation for the UITableView Parent Class,
is that it is supposed to return a cell, a UITableView cell,
so an object that represents a cell
in a table configured exactly as we want it.
And by configured, I mean what text do you want for the cell?
What buttons do you want on the cell?
What behavior do you want for that cell?
So in short, this method is called when rendering this row,
then this row, then this row, then this row, then this row,
it is my job to tell iOS how I want each row
to look and behave.
So what's interesting, though,
about this implementation is the following.
One, we have this static pointer declared here, so identifier
that points to a string that's statically declared as "cell."
This is completely arbitrary.
It could be "fu" or "bar" any word there, but it's going
to be used in the following way.
Down here, I declare UITableView Cell, TableView DQ Reusable Cell
With Identifier "cell," "fu," whatever word you've chosen.
So what is that doing?
Well, I'm checking if cell equals Equals Nil,
that means that there apparently was no reusable cell
in my queue, so nothing came back.
And so what do I proceed to do?
Well, it looks like a common paradigm here.
UITableView Cell, allocate it, then initialize it
with some long crazy named constant,
and also give it a re-use identifier of "cell," or "fu,"
whatever word you chosen.
Then lastly, change the accessory type
to be UITableView Cell Accessory Disclosure Indicator.
What is that?
It's like the little eye icon or similar on the screen.
All right?
So -- or rather, the little arrow that points to the right
that we saw on the TableView when we were in the app.
Then we proceed to do what?
We grab the object at that particular row.
We then update the text label on that cell
to be whatever the description is of that object, so in short,
the object that we put in that --
the object we put in objects was essentially a date,
and then we're just adding
that to the descriptive text on the cell itself.
And then we return the cell.
So most of that was just configuration details.
Maybe new in terms of the code we're seeing,
but not all that interesting except
for this If condition here.
What do you think the purpose is of the relative complexity
of these several lines?
Why this queue?
Why this reusable thing?
What's going on?
>> Make sure you don't overwrite the cell,
then just make sure it's unique.
>> Okay, so make sure you don't overwrite a cell.
Make sure it's unique.
True, but we could do that by just allocating a new cell
for every one of the dates in this table, or every one
of the words that I want to put in this table.
Why else might I be introducing this complexity of some kind
of queue of reusable cells?
>> Want to change the value inside?
>> Want to change the value inside, so that's true,
but why -- what's the motivation?
Let me press further.
Suppose that you can view 10 cells on the screen at once,
based on the height of your iPhone and the height
of your font, and you have allocated, let me say,
if you want -- if you only can display 10 rows at a time
but you've got 100 date because you've hit
that button 100 times, technically only 10
of those cells need to be in RAM at any given time,
because the other 90 are down here.
The user is not going to be able to see them,
so why bother keeping them in memory?
So if I give you that insight,
why are we apparently using this trick?
What's the motivation?
Yeah.
>> To make it faster and [inaudible].
>> Exactly.
It all boils down to memory usage and memory management,
so to your comment earlier about really the spirit
of keeping memory usage low,
you could absolutely just allocate 100 cells
for 100 items, and frankly the user is probably not going
to notice any latency when a scrolling through them,
because 100 is not that big.
But suppose for Evil Hangman,
you decided to make an application
that displays all 100,000 plus words at once,
and you scroll through that.
Then you probably will, depending on the hardware,
start to notice some latency because there's
so much RAM being taken up by all of those rows,
and it's completely unnecessary.
Of the hundred thousand, you can only see maybe 10 of them
at once, so you only need to have 10 actually resident
in memory at a time, so this queue is meant
to be a performance optimization.
So if you've ever use an iOS application that starts
to feel very laggy for some reason, it's probably
because they were trying to do too much, and potentially some
of that work was unnecessary, as might be the case here.
So this is illustrative of that kind of design paradigm,
especially as your data sets get larger and larger.
Okay. Let's not dwell too much on the other methods,
but happy to take questions if they arise
or are on your minds now.
All right.
So that just leaves us with one last class,
the Detail ViewController.
So this guy, if I go to the .H file,
looks pretty uninteresting, except for the fact
that he's got a UILabel and he's got a Detail Item.
I also see mention of IBOutlet.
What is that again?
What's an IBOutlet?
>> Reference to a thing that's declared in the Nib?
>> Okay, good.
So it's a reference to something that's declared in the neb,
so it's a means of my code talking
to my drag and drop interface.
And in this case, the thing in question is UILabel,
so how can I pull up Interface Builder and see that interface?
What file do I want to click next to follow this bread --
this trail of breadcrumbs?
>> Detail ViewController.Nib.
>> Yeah, so Detail ViewController.Nib,
and if I look there, it looks like indeed,
someone has just dragged and dropped a UILabel.
I know that because I can see its description down over here.
And when in doubt, too, if I go to the right-hand panel and open
that up, and notice that I'm on the Identity Inspector,
Xcode has a habit of dumbing things
down by saying Label hyphen Detail ViewController dot dot
dot, when really that's not all
that interesting programmatically.
You want to know what type of object is that really,
so in the Identity Inspector, which you can see at top right,
you can see that, oh, the thing I've just clicked is actually an
instance of UILabel.
That is what I have dragged and dropped, and again,
that's the connection between code, and the drag
and drop interface here.
So let's enter just one last question before we put this
template aside.
How do we somehow pass control off
from the Master ViewController to the Detail ViewController?
How do we make that transition?
We haven't looked at the code yet per se,
but where would you look if you wanted to answer that question?
How does clicking on a cell lead to a state transition?
What file should we look at?
>> Do you look at the method that's called
when it's actually clicked?
>> Okay, so we want to look at the method that's called
when it's actually clicked.
And how can I chase down that answer?
>> Ask in a selector into the constructor of one of the codes?
>> Okay.
>> [Inaudible] the Master ViewController.M.
>> Okay.
>> Hitting control X, control X is a selector.
>> Selector, okay.
So there's a selector for insert new object.
We saw that before.
Only one match.
>> There should probably be a protocol somewhere
that defines an interface between Master...
>> Okay. So let's see.
If I scroll down here, self a row, can edit row at index path,
TableView Commit Editing Style.
That doesn't sound right.
Oh this one, interesting.
And that's exactly right.
What Peter proposed is
that presumably there's some method that's defined,
maybe in that protocol we saw at the very beginning of the story,
that is what's called when a user clicks on the row.
And indeed that's the case.
It's -- this is a common paradigm, clicking on the row
in a table, so Apple went ahead and implemented
that base functionality for us, so if we want to listen
for that key press on one of those rows,
we apparently just have
to implement a method called TableView Did Select Row
at Index Path.
So what's going on in there?
Well, notice first, it takes two arguments.
The first is a TableView,
so that's what TableView did the user click on.
Maybe there's multiple ones on this screen.
And what, again to be clear, is an Index Path?
>> Section and...
>> Section and a row number.
So it's going to be like zero comma something
for the zero section, zero index,
and the actual row number.
All right.
So what are we doing here?
We again seem to be doing what's generally called lazy loading.
If the Detail ViewController does not yet exist, if it's nil,
what do we actually do?
We allocate it by calling Detail ViewController Alloc,
we initialize it with Nib name, Detail ViewController.
Notice when you call this method, you don't say .XIB.
Bundle is just referring to what folder is it in.
We just say nil because it's in the default.
Everything is organized at this top level.
And so once these lines of code have executed,
we now have a pointer to an object
of type Detail ViewController.
So we've got the thing in memory now, we just have to transition
from the Master to the Detail.
So what am I going to do next?
NS Date Object object.
So just to be clear, what is this next line of code doing?
On the right-hand side, we have what type of object?
What is Underscore Objects?
>> A mutable array?
>> An NS mutable array.
So if we index into it at a current row, that's going
to return an object of what type apparently?
An NS date, and on the left-hand side, we're allocating what?
What's the pop quiz here?
>> A pointer.
>> A pointer, good, to an object of type NS date.
So we're not allocating an NS date, we're allocating a pointer
to an NS date, so it's just 64 bits most likely,
not the full-fledged object.
Next we do Self.Detail ViewController.
Detail ViewController.
What is Self.Detail ViewController?
Where did we see that before?
>> Property?
>> So it's a property that we declared earlier,
and .Detail Item?
Well, what's Detail Item?
It's going to be set to the object.
Where did I see Detail Item?
If I go to Detail ViewController.H,
Detail Item was apparently a property that I stored here.
It's a type ID.
What does ID mean?
>> Any object.
It's a pointer that could be nil,
but it's a pointer to any object.
So this is just a generic way.
We could have been more explicit and stored NS dates.
Whoever with this template decided
to just genericize it a bit,
so we're storing something of type ID there.
So lastly in this line, we call Push ViewController
Animated Yes.
So the fact that it slides from left to right, as we can see,
is the following -- is the result of the following.
Notice the sexy left right behavior like that,
but if I instead change the bullion yes to bullion no,
stop the current running instance and rerun,
and now go ahead and plus, plus, plus,
click here, much less elegance.
All right?
That's what makes Apple devices Apple.
The sexy little slides back and forth.
All right.
Questions?
Okay. So you may never again use a Master Detail ViewController
template, and that's fine.
The goal of this was not to walk through just templates
that Apple hands to us,
but rather [inaudible] the design paradigms
that they're leveraging as a result of this
so that you can either start with something like this,
or something simpler, like the simple Single View application,
and begin to wire things together in the same way.
And what this is particularly illustrative
of is wiring stuff together, not using Interface Builder,
and dragging and dropping blue lines,
but writing much more code and doing it manually and precisely.
>> [Inaudible audience question].
>> IB outlet in...
>> [Inaudible audience response].
>> This guy over here?
Ah, good question.
So Detail Description Item.
For some reason, the developer who wrote this template seems
to have gotten bored with actually doing the wiring and --
rather the coding, and decided to wire it up so we can go
to the Nib file for Detail ViewController.
And if I control click on this thing,
we will see that Detail Description Label is wired
to file's owner.
And who is the owner of this file apparently?
>> Yourself, or the Controller.
>> The Controller.
The Detail ViewController, because recall, that's the guy
that initialized the Nib in In It With Nib Names.
So he is the file's owner, because he is the guy
that called this Nib file to life.
So that was the one instance of dragging and dropping.
Everything else in the Master was done in code.
>> Okay so that's why it's [inaudible]?
>> Yes. Oh, I'm sorry.
Missed that part of the question.
Yes, so if we go into Detail ViewController,
we have seen a slightly different feature here.
These attributes associated with properties,
the reason that this here is weak is that we do not want the,
what's the best way to say this.
This property in the Detail ViewController is not --
is pointing to an object that doesn't need to be kept around,
particularly if the Detail ViewController, once it goes
out of scope, as by hitting the back button,
disappears from memory.
We don't want to have a strong reference
to the Detail Description Label lest
that blue line keep the Detail ViewController
in memory unnecessarily long.
So in this really -- boils down --
the motivation for this is
because the Detail ViewController is coming
and going, we want iOS to be able to reclaim that memory,
and so we don't hang onto, in a strong way, these bluelines.
And that's the first instance I think we've actually seen
of that use of weak for that reason.
Good question.
All right, why don't we go ahead
and take our five-minute break here.
Will come back and start building something from scratch.
And we're back.
So recall that there's been a checkbox
that we haven't checked this far
because we've been using Nibs instead.
And Nibs are a deliberate design decision
because they've given us much more low level control
over our user interface,
but popular these days is another feature
that we keep unchecking, known as Storyboards.
Anyone familiar with these yet?
Used Storyboards?
If we check that, what we get out of the box?
So this is Apple's way of trying
to simplify the user interface process further,
at least for applications that follow some common iOS paradigms
like the TableView that we just saw, the Utility Application
that we just saw, and making it less necessary to write code
to somehow make ViewControllers interact.
So if we follow this next screen by clicking Next
with ViewStoryboards, what we'll get is an application
that looks a bit like this, and let me go ahead and open
up a different project called Storyboard from tonight's code,
and this will give us a view of exactly what's different.
In the Storyboard folder, the story begins as usual
with Main.M, and then up here we seem to have Main ViewController
and Flipside ViewController, so what I've done was start
with the -- which template as a starting point apparently?
>> Utility?
>> So the Utility Application.
And a couple of you did this I think accidentally maybe last
week when following along since it was pointed
out that your Nib file looked a little different, and it's --
or your UI looked a little different.
And indeed, if we go to Main Storyboard.Storyboard,
we see a user interface that looks like this
for utility application, and it appears that we're seeing
like two Nibs simultaneously: the Main ViewController
and the Flipside ViewController's UI
in the same screen.
But they're somehow connected via this transition,
generally known as a segue, and indeed that's what it is,
because when you use a Storyboard,
you essentially get one master file for your user interface,
and you wire this up all within itself.
And you specify in code exactly what you want to happen
when A segues to B. So the one line of code we need
to draw attention to really is just this.
If I go into my Main ViewController,
notice that this is actually pretty straightforward.
I've simply implemented a separate method this time called
Prepare For Segue Sender,
and this is the method that's apparently going
to be called whenever the user induces a transition
from the first controller to the second controller,
and you can see what's doing --
what it's doing here if segue identifier is equal
to the string "show alternate."
So this string, show alternate, is completely arbitrary.
Could have been fu, bar, baz, whatever.
But it's a string that we'll see elsewhere
and apparently what's happening, if that is the identifier
of the segue that the user wants to happen by having interacted
with the application,
we're going to call Destination ViewController
on the segue, set delegate to Self.
In other words, before the user transitions from this side
to this side, we apparently want to inform the segue
that the destination is going to be what ultimately?
Or rather, we want to inform the Destination ViewController
that its delegate is going to be Self, the main side.
So recall the same paradigm
in the Utility Application we played with in class
that you've probably begun with for Evil Hangman,
or are about to, whereby when you click that Done button,
you want the transition to go back and you need to know
to whom to return control,
in this case the Main ViewController.
So that begs the question,
where is this quoted string coming from?
Where is this identifier for the segue?
So if we go to the Storyboard, and I click on the segue itself,
not much happens over here, but notice that this is apparently
of type Modal Segue From Button, flip to Flipside ViewController.
That's the English friendly string.
I'm going to have to make my UI a bit of a mess and open up,
over here, the right hand panel, and with that segue selected,
if I go up here to the Attributes Inspector,
notice that the programmer who made this template, in this case
at Apple, to manually typed in an identifier of Show Alternate,
But again, that could have been fu, bar, any string there,
and that's to uniquely identify the transition.
So in short, if we want
to somehow wire together the user interface
in this different paradigm whereby both sides
of the application are in one file, we simply have
to define what happens when that transition occurs.
So I mention these now because if you want
to take things further, say for your own native application,
if you go that route for the third,
you'll find that this is a very common paradigm now
with iOS programming because it really eliminates a lot more
of the wiring that you need to do,
and it centralizes the UI in one place.
And as this picture kind of suggests,
if you have a particularly complex UI, like a menu,
and then a submenu, and other submenus and other submenus,
you can wire them all together
within the confines of the same tool.
And it's just a simplification.
Yeah.
>> Is there a disadvantage of wiring like the information
to the second page and then going back to the first page?
>> Good question.
Is there a disadvantage?
Not really.
The gripe people tend to have with Interface Builder
or using Nibs or Storyboards in this way is that you don't have
as much low-level control, and you can't necessarily --
might take -- sometimes take more steps to implement
than you want, and once you start having to write code
to talk to your Nib files and whatnot, at that point a lot
of people feel, oh, I'll just do it all from scratch.
And so that's why we just saw in the Master View,
the Master Detail Application, the master was all code,
even though the detail used a bit of wiring,
and the no Nib example last week was just all code.
So it's just a trade-off, and a lot of people,
seasoned iOS developers tend to prefer just doing things
from scratch, and of course if you're bored
with IOS's built-in UI in aesthetics, you have to do it
from scratch if you want to layer things on top.
Good question.
All right.
So let's start something truly from scratch now,
and based on time, we can pull a pre-baked cake out of the oven,
namely implementing an automated teller machine.
So a cash machine, a bank machine, that simulates the idea
of depositing money into a bank account
and actually doing some math to keep track
of the total account balance.
So let me go ahead and create a new project.
We'll do this as a Single View application just
to keep the focus now on the logic and less on details
like the transitions between scenes,
and let's go ahead and start.
I'll call this ATM.
I'm not going to use Storyboards.
I'm going to use the lower-level Nib approach,
especially since we only need one anyway.
I'm going to go ahead and click next, save it on my desktop,
and now I get our standard files over here on the top left.
We could tell the story as before,
but it's probably getting a little bit redundant now.
Main.M somehow invokes the AppDelegate,
somehow invokes the ViewController and the UI
for the ViewController comes from the Nib.
So let's go ahead and create a little bit
of an interface here for my ATM.
So I'm going to go ahead and make my whole background white,
just because, and then, let's see.
I want my ATM to look more like maybe a calculator
with a total input field up here,
maybe a total account balance down here,
and then a whole bunch of numbers.
So let's start to wire this up.
I'm going to go ahead and have a UILabel up top here.
I'm going to drag it to be as wide as I -- as is recommended.
Let me go ahead and increase that font size to make it,
oh, let's say 36, okay.
Now we'll go ahead and make it a little bigger.
And now let me go ahead and do another label that's
down here toward the bottom.
This is going to be my -- actually, let's just copy
and paste this so we get the same font size more quickly.
I'm going to go down here.
This will be my balance.
All right.
So now I need a whole bunch of buttons to represent this thing.
So I'm going to go into my rounded rec'd [assumed spelling]
button here, and let's see.
This will be the number, let's see, let's go ahead
and match this lest we get it backwards.
Let's go in, to save time, to the ATM, Xcode Project,
and dot dot dot so that we don't spend all day dragging
and dropping.
Voila. Now I have this interface.
So what's now on this screen?
Well, I write a line of the text, so just by clicking
in the Attributes Inspector.
I centered this field here and I added another UILabel just
to stay balanced, just for user interface.
So there's one label, two labels, three labels.
So these aren't input text fields per se,
but they're sort of output displays.
So in my code, I can display what the user's typing here,
and I can display what the user has in their account down here.
All right, so what might I want to do next?
Well, the goal is I want the user to be able to type in,
like, five, zero, deposit, in order to deposit $50 in his
or her account, and then I want to see 50 down here.
And then if I then do 10, one, zero, deposit,
I want to see a total account balance of 60 down here.
So we need somehow -- we somehow need to represent a few things
that are going on here.
One, all of these buttons need to be somehow connected
to my code so that when I push the number five,
and then the number zero, a couple of things happen.
One, those numbers get saved in RAM somewhere; two, they display
like a calculator would, five, zero, up here,
so I somehow need my code to talk to my interface
which is going to require a IB...
>> Action?
>> In this case, if I want my code to talk to the UI
and IBOutlet, in that direction, by contrast,
when I push a button, I want to trigger an IBAction to my code.
So I have some blue lines going in both directions,
or we can do it purely in code, as we've seen,
and then I have two special buttons: deposit, of course,
and then the clear button.
So before we get there, I'm going to go ahead and propose,
let me roll back in time,
so here's where we were a moment ago.
And let's assume that we're seeing now the cake being made
and then finally we'll skip to the ending here.
So as we're making this thing, I've realized in the top left
that this is an opportunity to have a model, the M in MVC,
because this is like a mechanical machine,
or a digital machine, that somehow has
to store account balances.
So what might I want to model in this program?
Well, maybe the notion of an account.
In fact, an account, like a bank account,
could be modeled pretty well as an object or an instantiation
of some class, and inside of an account is going to be one
or more pieces of data.
And the only one I'm going to care
about for now is the account balance.
So in order to do this, I'm going to go up to an option
that we probably haven't used but it's pretty straightforward.
File New file, so not a new project, just create a new file.
And you'll see an interface that looks a little overwhelming
at first because there's a lot of options,
but really they're just different templates
by which to start a new file.
And all I'm going to want is an Objective-C Class.
So I'm going to go ahead and click next, and I'm going
to call this thing account.
It's asking me what does -- what should it be a subclass of.
NS Object is fine.
Every other thing --
most everything descends from NS Object,
so that's fine for my purposes.
I'm going to go ahead and click next, going to go ahead
and click create, and voila, at the top left of my file,
I now have the ability to represent an account object.
So let's see what I've gotten for free.
In Account.H, I have interface, account descends from NS Object,
and in Account.M, I just have a blank implementation.
So now I have an opportunity, again for the first time,
to implement some notion of an account balance.
And I'm going to propose the following.
In my.H file, I'm going to propose a property that's going
to have, let's say, a sign, we'll come back to that
in a moment, non-atomic attributes.
I'm going to propose that this be an unsigned,
long, long balance.
So a couple details pop out here.
So one unsigned, just to be clear,
means that the value can only be...
>> [Inaudible audience response].
>> Nonnegative, so it can include zeros,
so that's what unsigned would mean.
So long, long?
What's that?
What's the role there?
>> [Inaudible audience response].
>> We want it to be 64-bit, so in this platform doing a long,
long gets me a 64-bit number,
and that just means it's pretty darn big.
I want to avoid what's generally called Integer Overflow,
whereby if we type in too big of a number, I don't want it
to roll over with this high probability just some
random number.
It turns out this is not an adequate defense.
We can still break this ATM and deposit an arbitrary amount
of money in our account pretty easily, but we'll see how to --
we'll simulate that in a bit.
Non-atomic, this just has to do with multi-threading.
I'm writing very simple code here.
There's not going to be two threads trying
to touch the account at once, though there could be certainly
in a world with multiple ATM's on a network.
But we'll keep it simpler.
And a sign now is different.
Typically we've seen what attribute in lines like this?
Yeah.
>> Copy.
>> So, okay, we've seen copy, but more commonly thus far
in our examples, we've seen strong, or weak, in this case.
So a sign literally does just that.
It gives me a setter that literally moves a value
from the right-hand side of an expression
to the left-hand side.
There's no checking for duplicate values;
there's no deep copying of objects.
And this is perfectly fine
for what's generally called the Primitive, like a long, long.
A long, long is just 64 bits.
To copy 64 bits, you just assign it from the right to the left
with an equals sign in between.
So there's no need for strong or weak, which have to do
with objects and pointers.
A copy also has to do with objects and pointers.
Assign is just for Primitive, so that's all I've specified here.
Okay? And by default, is this read write, or read only?
>> Read write.
>> It's read write, which means I get a setter
and a getter automatically
by having declared this property here.
Okay, so we're going to keep the account simple.
We're not going to bother with account numbers
or names or any of that.
We're just going to keep it simple
with our placeholder there, and now in my implementation
of this object, I might want to do one thing.
So it turns out an NS Object, recall,
comes with some default functionality in the form of an
In It Method, and that In It Method is defined
in the NS Object class.
And typically that method does nothing by default,
but it's an opportunity for us to do something.
What might you want to do in the way of initialization
when you instantiate an account object for the first time?
>> Set an initial balance?
>> Yeah, so why don't we set an initial balance.
So the signature for an In It Method,
if you look at the documentations for NS Object,
or just in general, the convention in iOS is --
or an object of C, is to have an instance method,
hence the hyphen, returns an ID, which is a pointer or nil,
and it's called In It, by convention.
So it's kind of like -- it's the initialization half
of a constructor.
An Alloc would be the other half.
Again a common paradigm is to say Now This If Self Gets Super
In It, so this is just a common way of saying, one,
call the parent classes implementation of In It;
make sure that it doesn't return nil,
because if it does return nil, I don't want it
to start doing work unnecessarily lest I
create problems.
And now if all is well,
I'm going to do Self.Balance gets zero,
and then I need to return myself.
So that's it.
If I deleted all of this,
we wouldn't be initializing the Primitive to a known value,
so this way, we have a default value
or we could be nice, right?
If the first time you sign
up for a bank account you get some free gift,
maybe you get $00 in your account,
and we could do that right here.
Yes.
>> Why do you have to do super Alloc and In It?
>> Super Alloc and In -- because that would be bad, because when
In It is called, Alloc has already been called.
So the convention is call Alloc, then In It,
so if In It called Alloc, that would be trying
to instantiate the object twice.
Good question.
All right.
So that's it.
This is a super, super simple model, if you will,
but it's representative of how we could go
about encapsulating information.
It may be in a fancier world, this information would come
from a database, and if it did, it could go in this model code.
But we're going to just as an abstraction
for what an actual account balance is.
So now, what more do we have to do?
Well, let me jump back to the pre-baked version
that looks now like this.
Notice that at top left I have the exact same code
that I wrote in advance.
I have a property called balance,
and I have an implementation of In It.
So if we go back to the Nib, I also did a few things
in advance consistent with what we said was necessary.
One, I wired all of the buttons to my code u IBActions,
and I wired my code to two different UILabels via IB...
>> Outlets.
So two directions.
Now how can I check what directions they went in?
Well, let me go ahead and choose the number seven,
and notice that if I hold control and click on there,
there's a whole bunch in this drop-down,
but the interesting one, recall from last week,
is Touch-Up Inside, that's this act, and the result
of that is to do what?
Files Owner Digit?
What could that mean?
>> [Inaudible audience response].
>> Call a method called Digit on what object?
>> File's owner.
>> On the file's owner, which in this case is going to be?
>> ViewController.
Exactly. So I'm in the ViewController, class is Nib,
and the file's owner is going to be the .M file,
so let's take a look at the .M file and indeed, there is,
nested among a few other methods, a method called Digit.
So I've declared this as an Instance Method.
It returns an IBAction by convention,
which is just synonymous with?
Remember your lower level C details?
Just void.
Just returns void, which means it returns nothing,
and it takes a pointer called sender,
and what is that going to be a pointer to?
>> The button that was pressed?
>> The button that was pressed.
So this is my way
of programmatically knowing what button was actually pressed.
So here's a -- a bit of a trick that we've leveraged
with the UIView class.
Notice in this first line of code, I'm doing the following.
On the left-hand side, I instantiate what?
>> Pointer to a UI Button?
>> Good. Pointer to a UI Button, and I keep asking this question
so that the answer is not allocate a UI Button,
which is not the case.
I've allocated a pointer to a UI Button.
On the right-hand side, what have I done?
>> Casting the center variable to a UI button...
>> Casting.
>> ...per style
>> Exactly.
So this is a C-Style cast whereby senders type?
I don't really know because I declared it as an argument
of a type ID, I don't actually really know what its type is,
so therefore I don't necessarily know what methods I can call
on it, and therefore Xcode doesn't know whether or not
to yell at me if I try calling a method maybe that doesn't exist.
It's okay to send messages to objects even
if they don't respond to them, but if I really want
to leverage my compiler in my ID here, it's nice if they can yell
at me when I'm do stupid things, so I can explicitly say
that sender is of type UI Button so that now, anything I do
with B will be known by Xcode as referring to a button.
Yeah.
>> Is there a difference doing in-line?
Like where you use [inaudible], cast B to the sender
to [inaudible] up there?
>> Good question.
That would be perfectly fine.
You could do this, let me scroll over, your code just starts
to look a little less readable, but that's perfectly fine,
and there's another way we could do this.
We don't strictly have to say ID up here.
We could do this and then eliminate this line altogether
and just refer to sender,
and the only reason I left it this way is really just
by convention.
Typically Apple always says ID as the type of the arguments,
and then casts it explicitly, but functionally it's the same.
The compiler won't yell at you.
Okay. So here now is a little grade school arithmetic that's
finally coming back to be useful.
Why does this line work?
Well, Self.Amount is referring to what?
I actually don't know what amount is.
So what is Self in this context?
What class are we inside of?
>> ViewController.
>> So this is the ViewController.
See I got out of sync here with my order of operations.
Let me go to the .H file and it looks
like there's a few things in here.
So let's actually pause for a moment and look at what's inside
of this particular ViewController.
So I have a property that's called account,
and it points to an account object.
Okay so there's my bank account.
There is my Controller linking to my M in MVC model.
So we saw that arrow promised in the picture earlier.
What's next?
A long, long amount.
I am not sure why there's an amount there,
so we'll come back to that.
There seems to be some duplication here
for some reason, but we'll come back to that.
And then here's the IBOutlet and the IBAction
that I mentioned earlier.
I apparently called it Balance Label, for the balance
at the bottom and Deposit Label
for the current number I'm typing in at the top,
just like a calculator.
And then I have some instance methods
that are declared down here.
As a spoiler, we're looking at Digit,
and this is the method that's going
to get invoked any time I touch a digit, a number.
Deposit is when I hit the green deposit button.
Clear is when I hit the red clear button.
And show is just a helper method I wrote
to keep my code organized and centralize all of the View code,
as we'll see in a moment.
So account, to be clear, is an account,
a pointer to an Account Object.
So now we go back to the .M file,
and now in Digit, what am I doing?
I'm storing Self.Amount, which was another unsigned long, long,
and I'm assigning it the return value
of Self.Amount times 10, plus B.Tag.
What do you think this is doing?
>> So amount just pulls what's the current --
displayed right now.
>> Good.
>> So every time you click a button, you want to multiply it
by 10 because every time you click a button,
then you're shooting the digits over.
>> Exactly.
>> By one digit.
>> Exactly.
So when I referred to grade school earlier, I just meant
to the process of every time you multiply by ten,
it shifts the number over to the left
and that's effectively the behavior you want.
Every time you type in an additional number,
you want to shift the current numbers over
and put the new one there, and you can do that arithmetically
by just doing multiply by ten of the current value,
and then add in B.Tag.
So this is curious.
So B is a UI Button, a B UI Button is a descendant
from a class called a UIView, and it turns out,
if we read the documentation,
that a UIView has a property called, take a guess?
>> Tag.
>> Tag, which is just a number field.
It's an NS integer that you can use for whatever you want.
So for simplicity, what I decided to do here,
in my ViewController, is this.
Notice I've got the number seven here selected arbitrarily,
but we can see it on the other numbers as well.
If I go up to the Attributes Inspector,
notice that the contents of this button are the number seven,
but they could have been seven,
even though that would look a little strange, but this is only
to say that this is a string up here,
even though it looks like a number.
So that's the label of the button.
But if I scroll down, and scroll down, notice that under View,
which is just Apples way of categorizing attributes
that are specific to UIView Objects,
what field does a UIView apparently also have?
>> Tags.
>> It's a tag.
So tag, all lowercase.
This is just a property in the UIView class.
That's a number that you can use for whatever you want.
Typically, the cleanest way to use this is with constants
that are defined elsewhere, so that there's some kind
of programmatic mapping to the values, but for simplicity,
because this is a very simple application,
I decided to just go through each of my buttons and because
by wonderful convenience --
coincidence, my buttons are meant to represent numbers,
I decided to assign each a tag that's identical to its label.
So I manually went in and made seven equal to seven,
eight is equal to eight, and notice that the number's going
to be changing there at top right.
If I click on two, it's two; zero, it's zero.
And then notice, deposit and clear are also zero,
but that's not a problem because I probably wired those guys
up to different methods so I don't have to worry
about confusing one zero for the other.
So if we go back to the button seven and control click on it,
notice that it will send the digit message
to file's owner whenever it's pressed up inside.
That means that digit gets called anytime I push a number,
and we saw on the .M file that that induces a little bit
of arithmetic where I multiply the current amount
in that top field by ten.
I then add B.tag to it, and then I call my Helper Method show.
And show, this is not something that comes up iOS.
I wrote it myself.
It was just my way
of centralizing all the code related to updating the UI,
and it looks like this.
I have two lines of code, even though they wrap,
and I'm setting my Self Balance Label Property,
the text thereof, to the result of calling NS strings,
String With Format Convenience Method,
passing in this very cryptic looking string,
Dollar Sign Percent L L U. What in the world does that mean?
What does the dollar sign mean?
>> Is it a dollar sign?
>> It's a dollar sign.
Money. Okay?
So percent L L U is a placeholder that represents?
>> Long, long unsigned value.
>> Exactly.
A long, long unsigned value.
So if you're familiar with C,
percent D is what you typically use for a decimal number,
but in this case, we want a long long and unsigned.
So cryptic, but it's perfect for what we want for our long,
long -- our unsigned long, long.
What do I want to paste into that value?
Comma Self.Account.Balance,
whose type is, again, long, long.
So I called this a Convenience Method.
In what sense is String With Format a Convenience Method?
What type of Method is String With Format,
apparently, based on the snippet?
>> A Class Method?
>> A class method.
Class method because we don't call Alloc.
You just call it directly so it's a Convenience Method,
excuse me, in the sense that you don't have to call Alloc,
you don't then have to call In It and jump through these hoops.
You just call this method.
And again, and I think we said this a couple weeks ago,
this is a very common paradigm in iOS.
If you have a class called NS String, or String,
having Convenience Methods that start
with roughly the class name and then With is a common way
of instantiating objects without calling Alloc,
so common paradigm is all.
Lastly, the thing done here is identical.
We're just doing the same thing with the current amount.
So notice the dichotomy.
I've got two variables called amount.
One is in my ViewController, and where's the other?
>> [Inaudible audience response].
>> In the Account Object, and notice the distinction.
What's in my account is what I've already deposited,
but what's in the other variable called Amount,
which is in the ViewController, is just storing what value?
>> What the user has typed in.
>> With the user has typed in thus far.
So if we run this thing now,
even though we haven't seen quite all of the pieces,
and we pull up the actual user interface,
and I click the number seven,
that digit message has been sent.
We have done the math of multiplying zero by ten,
which is the default value, plus seven,
and then I've called the Show Method,
which updates the value to be seven.
But only once I click deposit here is the deposit
method called.
So let's check that.
If I go to the Nib, and I go to control click on deposit,
scroll down here, touch up inside is mapped to deposit,
so now, if I want to see what the positive does,
if I go into my.M and scroll
down to here, that is doing what?
Self.Account.Balance Plus Equals Self Amount,
so it's adding what's actually
in the Controllers variable to the ATMs variable.
What am I doing with Self.Amount Equals Zero?
Well, I'm just clearing my local value
and then I'm updating the UI by calling Show again.
So this is actually a really clean example of MVC
by keeping these barriers between everything.
The Controller's doing all of my logic
and my temporary arithmetic, but once I'm ready
to make the deposit do I talk to the model,
and only once I've done that do I show things
by having the Controller call on the View by way
of this method I called Show.
All right.
So which method is probably going to be pretty similar?
Clear? If we look at clear, super simple.
It's the result of having wired things together,
but suppose I've screwed up and I forgot to wire
up the Clear Method, which I can simulate
by clicking the X there.
And so now the clear button has no effect.
From what to what do I need to click and drag in order
to reconstruct that IBAction or IBOutlet?
First what is it?
>> IBAction?
What do I have to go -- do?
>> [Inaudible audience response].
>> Click on the clear?
All right.
Holding control, go to where?
>> File's owner.
>> Files owner.
Let go. There I see a list of all
of the methods that I can call.
The one that doesn't have a hyphen means I just haven't
wired it up yet.
I'm going to go do that, and now we've fixed it.
Conversely, if I screwed up my label, which currently,
if I click on this with control,
is mapped to Deposit Label, how do I fix this?
Well, I can control click on my label,
go to files owner, and, hmm.
Just the other way.
So IBOutlets go from files owner to deposit.
There it is, Deposit Label, wire it up,
and now I've resurrected the actual interface.
Any questions?
All right.
So let me propose with this particular one,
especially when it comes time to your native applications,
if you want to start with something from scratch,
think about using that as the beginnings of an application
because it draws these fairly clear lines between MV and C,
which recall is just the picture that we looked at earlier,
and as well, last week.
All right.
So let's forge ahead to something's that going
to give us a new capability altogether.
Rather than focus on reinforcing some of the things we've done,
let's go ahead and consider this.
It turns out that there's a whole bunch of ways
that we can start storing information.
To date, we have not stored any information persistently
in a program that we've written.
Every time you quit the application,
any things that you've been storing in variables,
anything you've stored in properties,
just disappears altogether.
But it turns out, in iOS we can store things in a number
of formats, so we have things call Property Lists,
which we've actually encountered before.
Something called NS Defaults or settings, SQL Light,
XML or json, even something called Core Data,
so Property List.
We've seen those before.
What's a Property List, or P List, file?
.P List? Yeah.
>> It's a dictionary of strings.
>> Exactly.
Is the dictionary of strings.
It's a file containing key values pairs and we've seen this
in Xcode in the form of a nice little pretty table form
with keys on the left and values on the right,
but that's just the user-friendly way
of showing you what's really an XML file with data types
like strings and integers underneath the hood.
But it's useful, and if you've dived into Evil Hangman already,
you know that this is the format in which we've provided you
with a whole bunch of words.
It happens to be an XML file underneath the hood,
and you can see as much if you actually download that.
In fact, let's go over to the distribution code,
and if I go to CS76.net/projects,
and we have the Full Words dog P List file there.
If I try to open it in Xcode, it's going to open
in this big chart here, which is kind of misleading
because there aren't really keys called item zero item one.
This is just their way of representing an array
in this table format, but if I instead go
into my downloads folder here and I open up Words.P list with,
let's say, Text Wrangler, which is just a simple text editor,
we are going to see this, which is XML.
If unfamiliar, XML is like HTML but you get to make
up your own tag names,
and so here we have an element called Array,
and then a whole bunch of strings.
So that is what we have given you for this dictionary,
and there's thousands and thousands of lines here.
So this is actually a perfect candidate
if implementing a program that listed all these words,
not to keep all of them around in like UITable cells,
if you were using a TableViewController
like we did earlier.
So with regard to storage, Property Lists are nice
when at least you have static information that you want
to shift with your application.
But they can also be used effectively to store defaults.
You can store value pairs, even when an application quits,
and one of the things you'll get to use an Evil Hangman or dabble
with in lab is NS Defaults, which is an interface
for storing information persistently in applications
so that when it quits, you can actually reload those same
values after the fact.
So what kind of uses might persistent storage
like that have for an application?
Why is this useful?
>> If you got a call while playing your game,
then you could store data and when they hung
up the call, you could resume it.
>> Okay, good.
So if you got a phone call, it interrupted your game,
you could then reload the information that the game --
the state that the game was in so
that you can continue playing it.
So to be honest, you probably don't need to use Property Lists
for that because so long as the application is backgrounded,
you can keep stuff in RAM still, unless the user quits,
in which case they're at a loss.
>> I was talking about NS Defaults.
>> Oh, I'm sorry.
So NS, okay so well, and even NS Defaults.
So NS Defaults are truly meant to be default values,
not state remembrance for the state of the game.
So defaults would be like do you want the sound
on or off by default?
Do you want -- what's your nickname by default?
So NS Defaults are good for things like that.
Configurable options that the user might change in the game.
Settings is just another UI.
A lot of applications, like in Evil Hangman,
will have settings built into the application, for instance
on the Flipside, and indeed that's
where you can store things like the preferred word length
and number of guesses, and in NS Defaults, if through that API,
which ends up writing a file into the iPhone or to the iPad
or the like, but you can also create write code,
that allows you to hook into the settings icon on the iPhone
or the iPad where you can move your settings there.
It's really just design decision.
What people tend to do for simple settings,
if you only have a few, they put them in the application itself.
If there's lots and lots of settings,
some people factor them out and put them
under the settings icon on the phone.
It's a little more annoying, though, because you have
to exit the application and go to it to actually get at them.
But you'll find that this is as easy as writing key value pairs
to an object, so more on that with Evil Hangman.
What's SQL Light, if familiar?
>> Like file SQL.
It stores a SQL accessible database in a [inaudible] file.
>> Exactly.
So SQL, a structured query language, is a database language
with which you can write information to a database
and read it, and use syntax that allows you
to search the database fairly easily.
You don't have to resort to linear search all of the time.
And it's nice because you don't need a server.
You don't need MySQL or Postgres or Oracle or anything like that.
You just store it in a binary file
in the same folder typically as your code,
and what SQL Light is, it's an API that lets you read and write
from that file using select and insert and delete
if you're familiar with that feature of SQL.
The catch is, in iOS, the SQL Light library is implemented not
in Objective-C but in C, which means the code looks horrific.
It's very useful, it's very powerful,
but it's also a bit arcane,
and so people typically use other constructs,
a couple of which we've discussed.
XML, meanwhile, or json, is typically used
when transporting information these days across the wire,
so Property List or XML, but if you were
to have your own arbitrary format, typically that's
for a game or a program that somehow grabs information
from a server on the Internet.
These are very useful data formats
for exchanging information.
And then finally there's Core Data, which is an iOS --
which is an Apple SDK which allows you
to abstract the notion of a database altogether
and define your database schema, define the keys
and the values, the relations.
Among them, using a very graphical editor to wire things
up a little more high level.
And you had a question here.
>> Is it possible to query a regular expression in SQL light?
>> Is it possible to query a regular expression in SQL Light?
Simplified ones.
SQL supports like queries where you can use a subset
of Perl's regular expressions, or, which are common
in other languages as well.
So sort of.
Good question.
All right.
So let's actually -- let's go back over here and let's go
into tonight's sources, and let's go into P List.
So I, in advance, downloaded the P list file earlier
on my own computer over here.
Not that when.
So now if I go into P List,
and go into the distribution code here, we'll see some
of the usual friends, and let me go
into Main.M. Okay, no surprises there.
Let me next go
into AppDelegate.H. No surprises there.
AppDelegate.M. No surprises there.
It seems to be handing off control now
to ViewController.H. Really nothing going on there.
ViewController.M. Finally,
there's something going on in here.
But let's wait.
Let's go to the Nib file, and for some reason,
my example involves cities in California.
So this is always been a stupid feature of Interface Builder.
When you drag and drop a UITableViewController
into an application, rather than show you your data
or just blanks, they arbitrarily show you cities in California.
Those are not in the application itself.
It's like a screenshot
of someone else's application, but mildly confusing.
But if I now go back to my code, let's see what I'm doing.
So recall that we looked
at the master Detail Application earlier,
which was a little complex, and I've stolen some
of the simpler ideas from it,
just to implement the following application.
If I go ahead and click run up here, woops,
and let me quit the old simulator, and let me run this.
In the latest version of the simulator,
it's going to pop open, and you might see some familiar words.
So these are from our Property List called Small.P List,
which I downloaded from the courses website.
Recall that the product specification gives you a super
short list, just so you can tinker without worrying
about hundreds of thousands of words.
So that's just an XML file that I've literally dragged
and dropped into the project,
and somehow in code I'm opening this up.
Yes.
>> [Inaudible audience question].
>> Yes, you should.
It's because I made these on another computer
and that one, there we go, yeah.
So with things like this, I'll go --
I'll fix these and re-upload them
so you don't see these little warnings.
It's because the computer I was creating them
on was a slightly different version.
Short answer, your code should have no warnings, therefore do
as I say, not as I do.
But I will fix that.
Okay. So this P List file, I literally just dragged
and dropped into the supporting files folder,
but that's not really a folder.
I could have put it anywhere into the project,
and so that means all of the logic must be in this .M file.
So let's see what's going on.
This is my ViewController class.
I have chosen to implement this familiar method now,
In It With Nib Name Bundle, and what am I doing in there?
One, I'm calling the parent classes version of that method,
so that's familiar construct, checking it's return value
to make sure it's not nil,
and then I'm apparently loading words.
So how do you go about loading an XML file,
specifically a Property List, from your application
if you've dragged and dropped it in there or added it
by going to File Add File?
Well, I apparently call NS Bundle Main Bundle, so this --
this is a way of saying to iOS, give me essentially the path
to the default folder,
the default root folder of this application.
Then give me specifically the path for the following resource:
"small,", and what data type is it?
P list. So this is a way of telling iOS,
give me a file called P List, sorry,
give me a file called small dot something.
That something is P List because it's of type P List,
and this helps it know how to load the file,
whether it's a Property List, a binary file,
or some generic text file.
Then I'm out doing this.
On the left-hand side, what's going on here
in this highlighted portion?
>> [Inaudible audience response].
>> Good. I'm creating a pointer to an NS Array Object,
and on the right-hand side, I'm calling NS Array Alloc In It
With Contents Of File.
So there's a bunch of different ways to do this.
I have chosen to use NS Arrays Alloc method, and then the
In It Method, called In Its With Contents Of File, and it turns
out that if I read the documentation for that method,
it just knows how to load that information into the file.
But I thought NS Arrays were unmutable?
Were immutable?
In other words, I thought you couldn't change them,
but I'm clearly initializing this one with words.
How do we reconcile that?
What's that?
>> You never allocated or initialized it.
>> I never allocated it or initialized it,
but I did allocate and initialize it here, right?
>> Not on both sides.
>> You haven't changed the arrays
and you just have it typed NS Array pointer.
>> So that's okay, on the left-hand side.
But why is this not a mutable array?
I'm adding stuff to it which means I'm changing it, right?
>> [Inaudible audience response].
>> Yes, that's the key distinction.
If you could never mutate arrays,
you could never have anything in an NS Array.
It would be a useless object.
But in this case, we have an NS Array that's being initialized
at the point of allocation with the contents of a file,
so the fact that it's an NS Array just means I can't change
it after this line of code.
And that makes sense, because if this application is just going
to show this list of words, much like Evil Hangman is going
to have a long list of words in its memory,
you're not going to want to change it.
You just want to have one copy of that lying around,
and it's slightly more efficient
to have the NS Array class instead of the NS Mutable Array,
because one, there's less functionality,
there's not the editing code related to it, and two,
you protect yourself against yourself.
You can't accidentally delete a word from your dictionary
if you've said to the compiler, this is an immutable NS Array.
All right.
So lastly, I'm just remembering that pointer by assigning it
to my property called Words, and then I'm returning myself.
So at this point in the program, I have loaded that Property List
into memory, stored it in a property, so now I have access
to an NS Array that I can iterate over
and do whatever I want.
So the application now looks like this.
It's a table of words and I now somehow have to render one, two,
three, four, five cells,
but I don't proactively push the cells to the UI.
I'm instead going to have the -- the iOS is going to ask me,
what do you want at this cell?
What do you want at this cell?
Or rather, what do you want at this row?
This row? This row?
And I have to return a cell to it.
So if I go back to the code, notice that we have this thing,
number of sections in TableView, so that's okay here
because it's just one big table.
There's not different groupings.
As an aside, if I go back here,
let me see if I can show you the opposite.
If I go into settings, this is a UITableView, so if you go
into an iOS device, you've seen to UITableView's for years now.
Those -- this is a UITableView with one, two, three,
at least four sections, each
of which has some non-zero number of rows.
So that's all we mean by sections.
But the game we're playing,
or the program we're using here just as one such section
since we don't see the gray.
So what next?
This, actually let me delete for simplicity
since it's not necessary here, and now we have TableView,
Self or Row At Index Path.
When is this method called?
When or why is this method called?
What's that?
>> [Inaudible audience response].
>> When you try to get a cell and you pass in the Index Path,
yes, so this is really -- the operating system is going
to call this method or more specifically, the Controller,
is going to call this method, or rather the View is going
to call this method When I Want To Render A Cell On The Screen,
it's going to say what belongs at section zero, row zero.
What belongs at section zero, row one, row two, row three,
and my job, as we saw earlier with Master Detail, is to return
to this thing an object representing that row
in the table with whatever text I want,
whatever buttons I want inside.
So we have this same trick using the reusable cells.
I'm using "cell" again this time.
If not, I instantiated as needed and then down here,
I am initializing the cell as follows.
One, I'm setting it so-called selection style
to be UITableView Cell Selection Style None.
What does that mean?
It just means that when the user's finger clicks
on this TableView, like I'm doing
with my mouse, nothing happens.
It doesn't become blue, it doesn't get selected.
>> So UITableView is getting rows [inaudible]?
>> Correct.
It's asking me what do you want here.
What do you want here?
And I have to hand it back the rectangular cell effectively.
Exactly. And then I'm setting the cells text labels text equal
to be whatever is returned from the object at index row,
so what's at index zero, what's at index one,
and then I'm passing that message to words
so that I get the zero object, the one object,
two object, three, and so forth.
And if I change this, for instance, to that, semicolon,
and rerun the application, what I should get,
despite all of that effort to store data,
is just the same string again and again and again.
So that's truly a method that's being called.
Finally down here, this one's different.
Number -- TableView number of rows in section,
this is the method that I'm going --
that's going to be invoked
when asked how many rows the section zero have
so that iOS knows how many times to ask you for the cells.
In this case, I have not hardcoded a value
because I don't remember how many words are
in the Property List, and maybe it would even change
with an update.
So we pass in the Count Message to Self.Words,
which gives me the array's length.
Yes.
>> So in case where you're passing through a file,
we have an array that's not immutable.
You're editing the actual file itself, I'm sorry,
the P List itself in your-- ?
>> No editing has happened to the P list here.
>> No, but I'm saying in terms of like if you wanted to --
if the P List had like more contents,
this would already account.
>> Yes.
>> Okay.
>> Exactly.
This is good design, because even though I could go
to the application and I could do a one, two, three, four,
there's five words in my P list, I could just write return five.
The catch is that whereas it's reasonable to assume
that my UI has zero, has one section forever,
because that's how I designed the user experience to be,
with just one big TableView, no notion of sections,
that in theory could change, and it's a poor design decision if,
not only do I have to update the Property List in a year
when I ship a new version with ten words and not five,
but to also have to change it there.
It's just inviting bugs and unmaintainability.
So that's all.
All right.
So nice and sexier maybe, but let's actually do something
where we interact with the glass of the screen and do something
like clicking or dragging or pinching, and see how we can add
that element, particularly
as you contemplate what you might want to do
with your third and final project.
So it turns out that iOS supports a whole bunch
of gestures, and you're probably familiar with these naturally
if you have a device like this, but they all reduce
to some key class name.
So we have things like UITapGestureRecognizer.
This is the type of object that if you instantiate,
you have the ability to detect that on an arbitrary portion
onto the screen, not necessarily right on top of a button,
which is handled for you automatically.
Pinch, which is doing something like this often to zoom.
Rotations, kind of twisting your fingers around,
swiping left to right, up to down.
Pan gesture, if you want to move something across the screen
and long press, if you want to click and hold for like a second
or two, that, too, can be detected differently.
And if you've used Google maps or Apple Maps or the like,
you've experienced a bunch of the different UI mechanisms.
So how do we start doing that?
Well, let me go into some code in our last project here
for the evening and open up the one called Gestures.
Now in advance, I went on Facebook
and downloaded a few photographs.
Let me go ahead and run this application,
and we have this application here.
And if we swipe to the right, there's his graduation.
And one more, in his plumbers outfit from this weekend.
So we can keep flipping through this, and each time I swipe
from right to left, even though you can just barely see my
mouse, it's like I'm sliding my finger from left to right.
And I kept it simple.
I didn't do it quite so that he's sliding off the screen.
As soon as I start sliding, it just jumps off to the side,
just to keep it simple.
But also, if I click and hold on, like, his nose,
it's going to nag at me because I'm using a long press
gesture recognizer.
So how do we go about implementing this
and implementing that kind of functionality?
Well, let's go into this.
So in my project here, I've got some familiar files
and some new ones.
Under supporting files, I have three photos of Rob,
so these are just JPEGs that I dragged and dropped
after renaming them, after downloading them from Facebook.
I encourage you to friend Rob on Facebook.
If you then drag them into the project,
I can now access them programmatically.
And so now, I can do something like this.
In Main.M is some usual code.
In AppDelegate.H, is some usual code.
In AppDelegate.M is some usual code.
So nothing new here.
We're building on the same principles as before,
so the magic must be somewhere in my Nib
in my ViewController files.
So my ViewController.Nib file also looks very simple.
I dragged and dropped a class called UIImageView,
which is like a video player, but for images.
It's just a placeholder for single PNG or gif or JPEG
or the like, and I configured it to just fill the whole screen.
So I need to somehow programmatically have access
to that.
So a good place to start, again, when downloading code
that someone else wrote or that you download online as part
of a bigger project, is just control click on it,
and it looks like there is a ImageView Property somewhere
that's pointing to file's owner.
So there's some kind of linkage happening here,
some kind of outlet to the files owner.
So let's look at my.H file, and if I go into my.H file,
nothing there, that's interesting.
ViewController.M, so I've tried
to take things one step further here.
Thus far, we've been putting properties
and method declarations in our .H files,
which is a common convention, but it's not strictly necessary,
because if all of my methods are implemented in this same file,
and if no one else is going to be importing my.H file,
and they probably shouldn't be importing my ViewController.
You would typically import utility classes,
or files with constants, or files for models and the like,
there's really no reason for me to advertise to the world
in principle in my.H file all of this internal functionality.
So I can certainly just declare these properties as private
by putting them in this file, and I say private typically
because again, you can still send messages to objects.
They may very well respond, but just in the interest
of not advertising features,
much like Apple does not advertise certain APIs,
they keep them private though people figure it out,
I've decided to declare all of my properties here
in this file my.M. So I seem to have a few properties.
One is a bullion called Alert In Progress,
and I ended up using that.
If I fast forward to the end of the story, because I needed
to remember if and when I had touched Rob's face for too long
and therefore trigger the AlertView, because I ran
into a bug through trial and error that if I kept holding,
I might get multiple AlertViews, and I didn't want to do that.
So I wanted a simple locking mechanism
to make sure I only open one AlertView ever.
So next I have an ImageView pointer to a UIImageView,
and that's my IBOutlet, so that's the wiring
between that IDImageView --
sorry, that UIImageView and my code.
Then I have an index.
I'm not sure what that is.
And then I have some Robs in the form
of a pointer to an NS Array.
So let's take a guess.
What is going to go in that NS Array probably?
Yeah.
>> The images?
>> The images.
So specifically maybe the names of the images that we'll see
in just a moment, and then the [inaudible] it's called index?
>> Where you are.
>> Where I am.
So I realize again by thinking through the design of this,
if I want to implement this -- this sort of carousel of Robs
and I want it to wrap around so that the third image goes back
to the first image, I decided just
to use an index that's going to be a 012, 012,
and I can use some modular arithmetic to wrap around,
like you might've done in other languages.
So that's where this is going.
Meanwhile, I've got some private methods, private only
in the sense that they're not advertised in my.H,
called you -- Alert View Did Dismiss With Button Index.
We've seen that before.
When is that method called?
Think back to last week.
>> [Inaudible audience response].
>> When the user clicks the cancellation button,
however labeled, that big default button.
I now have another method called Handle Long Press,
and the Handle Swipe, and those are implemented
to receive something called a Recognizer, so a pointer
to some kind of logic that has recognized what the user has
done so I can glean some information about it.
So now if I scroll down, what am I going to do when --
let's do the Handle Long Press, because it's a little simpler.
So when I click and hold on Rob's nose,
or frankly anywhere on the image.
It doesn't matter based on how I've implemented this,
what is going to happen?
Well, iOS is going to recognize that you're holding Rob's face
down for quite some time, and therefore some code's going
to get executed, specifically this method, Handle Long Press.
I'm going to be passed a pointer to the recognizer,
in case that's useful, and what I decided to do
with that information here is what you saw.
I'm going to first check, wait a minute,
is there already alert in progress?
This is the bull that I referred to earlier,
just to make sure we don't get stuck in an infinite loop
by holding his face for four seconds instead of just two.
Then I set it to yes, so that I remember,
and this is single threaded code at this point,
so it's not a problem if I'm still holding down.
Then I'm going to go ahead and allocate a UIAlertView,
and we saw this code last time,
even though the words are now different.
It's going to say, hey, stop that.
I have a delegate of self, so not nil, and a cancel button
of fine, so this delegate of self is used for what purpose?
>> [Inaudible audience response].
>> To tell the ViewController that it is done,
that the user has dismissed it specifically.
So not the View, the ViewController,
and that is what invokes this method, recall,
which we said a moment ago is the method that's called
when you click that close button on a UIAlertView.
So all of that stuff is pretty much identical
to what we saw last week.
So that's the method that's called When I Do A Long Press,
but how did I teach the program to even listen
for those long presses on the image in question?
Well, if I scroll down, we look to a couple of places here.
One is In It With Nib Name.
So this again is going to be
that method that's automatically called when you are using --
when you are using Nibs in your program.
This is the opposite of using Storyboards, for instance,
but there's a similar mechanism for those.
So In It With Nib Name is copy and paste it essentially
from before, but I've added a bit of code in the middle.
I first said Alert In Progress, no,
because I want to know by default.
There is no long press, and that makes sense.
When the program starts, no one's touching it by default.
And then I prepare the Rob, so to speak, and that's one way
to initialize the array.
I Alloc an NS Array, In It With Objects,
and if I am not loading it from a file, for instance,
just from a comma separated list, the syntax is string,
string, string, nil, all in square brackets.
So that much like C is how you can declare an array statically.
The nil is important.
You have to terminate the cease-file array
for that reason.
On then Self.Index Gets Zero, what does this mean?
What's the -- ?
>> Start at the zero.
>> Yeah, start with the first Rob at index location zero.
So next, View Did Load, recall,
is the method that's called once your View,
your user interface has been loaded, and this is your point
at which to start configuring some last-minute details,
after everything's been opened
up from the Nib file, for instance.
So this is new code, but hopefully pretty readable.
So notice I first call the parent class's version of this.
Woops, the parent class, so I call Super View Did Load,
then I load the image.
So Self.Image View.Image.
Self.Image View is what?
>> A property.
>> It's a property of type UIImageView.
If I read the documentation for UIImageView,
turns out that a UIImageView has a property called image whose
value is a pointer to a...
>> UI.
>> UIImageObject, apparently.
We've not seen this before, but you can now it reader
from the code itself, so this --
this class here is called UIImage.
Turns out it has a Convenience Method called image name whereby
if I get the I'th Rob at the current index,
so give me Rob's bracket zero, but do it dynamically
in code here, that is going to give me an Image Object,
UI image with Rob, and I'm going to plop it into the carousel,
essentially, the UIImageView that allows me
to show the image to someone.
So now I'm going to listen for presses on Rob's image.
So code's a little ugly,
but what I'm doing is declaring a pointer called Long Press
Gesture of type UI Long Press Gesture Recognizer.
I am assigning it the return value
of calling UI Long Press Gesture Recognizer Ella,
so just give me one of these recognizers.
I'm initializing it with a target.
Self, we'll come back to than a second.
Action called Handle Long Press.
So in layman's terms, this is listening for a long press,
but in slightly more technical terms,
what are we telling the UI long press gesture recognizer object
exactly with in it with target and action here?
>> First you're saying that the message to be sent
when the long press happens is Handle Long Press.
>> Good.
>> And you're also saying you should send that message
to self, so the View Controller.
>> Exactly.
So this, again to recap, means when you detect a UI long press,
a couple seconds down with your finger,
send the message Handle Long Press,
which could've been named anything.
I came up with that method, but pass it to specifically myself,
the same ViewController.
And that's why the method earlier
in the file is indeed invoked when we hold down the --
when we hold down ones finger and call Handle Long Press.
So the other recognizers, let's see first before we see them
in action one last time, listen for right swipe.
So how do I do this?
Same idea.
I allocated UI Swipe Gesture Recognizer.
I initialize it with Target Self,
and this time I tell it Call Handle Swipe
when the user swipes from a certain direction.
But what direction is that?
In this case, I have to do one additional step.
I have to specify the direction, and according
to the documentation,
swipe gestures have a direction property
and this crazy long constant is what specifies.
When I go from right to left,
essentially this is what should actually happen.
What should happen?
Well, here is how we add to an ImageView,
just like we did a few lines ago for the long press,
this is how we add a recognizer to an existing view object
that is on this screen.
You create this recognizer, and you sort of glue it
down onto the view so that
that view triggers these various actions.
Listen for left swipe.
I've done that with a separate line of code
at the end there just by changing the constant
to be this, and that's so that we can swipe right to left,
or left to right, to increment or decrement the Robs.
And if we go back up here, let's look at the code.
Let me fix this.
Rob we swapped in this year.
Handle Swipe works how?
So this is the method that's called when we swipe right
to left, left to right.
This is how we figure out the direction.
We ask the recognizer that was passed
in via the sender argument what direction was --
were you sent in.
I'm using a switch, which is like an If Else,
but just done slightly differently syntactically,
I decided to do this.
If the user has swiped up down or down up, do nothing.
Now technically, these lines of code do nothing useful.
I just left it there for explicitness sake,
but it immediately breaks
which means there's no effect whatsoever.
Meanwhile the direction left, down here, has to do a bit
of math, and it took a moment to kind of think about this,
but I'm updating the index value to be, when I go from right
to left, plus one, and then I need to wrap
around with some modular arithmetic based
on the length of the array.
Down here meanwhile, if I wanted to wrap
around to the other direction, I had to effectively subtract
by one, but I wanted to make sure that we didn't go negative,
so I also have some addition in there just to make sure
that two goes to one, one goes to zero, zero goes to two,
and doesn't accidentally go negative.
So just some basic modular arithmetic there.
And then lastly, what actually updates Rob,
and updates him instantly, is to change the property called Image
of the ImageView IDOutlets to the image named whatever Rob is
at that particular index.
So could have implemented this in different ways.
Could have stored the actual images in an array as opposed
to the file names, but we kept it simple in this way
so that we could actually see the strings explicitly
in the code, but this is how we can now start listening
for these things, and any of these kind of interactions,
pinching and zooming and rotating,
is implemented similarly by implementing one or more
of these recognizers, and then responding accordingly.
>> Is this a handle that we have for competing recognizers,
say at -- for the long tap, and actually it's a tap
and it's a long tap because it only triggers long taps?
>> So in that case, if you're detecting tap versus long tap,
if you're holding long enough, it will only be a long tap.
That's what defines it as long, holding it slightly too long.
If you do it within the window, and I think it's one
or two seconds, that would be a tap.
But you won't get both of you're holding down like that.
You'll just get the long tap.
>> So there's no way
that property gesture called [inaudible]?
>> You could potentially induce multiple ones.
You can give priority to them effectively by listening
to which one fires first, and you can think of this again
as layers, as to which layer is going
to receive the gesture first
if you've added to multiple objects.
But for the case you describe, they'd be mutually exclusive.
Other questions?
So out of curiosity, how many people are leaning toward web
applications for their third and final choice of projects?
Did I give a bad answer there?
Okay. All right, a few.
And iOS applications?
And undecided?
Okay. So not -- not bad.
So start thinking about that, even though I know you're
in the midst of Evil Hangman, but you'll soon get feedback
by this Wednesday from the teaching fellows
on the mobile local projects, so you can start thinking
about what you could've done better there,
how you might do things differently for a third
and final project if you go with HTML 5 and JavaScript.
Also think about the native applications and again,
when the specification goes up, you'll see that step one is
to float the idea by your TF, and he will confirm
or deny the appropriateness,
the viability given the limited time,
and will help guide you toward something that's doable,
so that in a few weeks' time, we'll all have some cake
and some exhibitions the projects.
Why don't we call it a night here,
and I'll stick around for questions.
See you at lab.
[ Silence ]