[ Silence ]
>> Welcome back.
First thing first, we have a new team member,
Chris Gerber [assumed spelling].
So, some of you probably already heard from him
as he being your point person, but he's here to help.
Second, don't forget that your project is due next Wednesday.
So we are diving into iOS/Objective-C today.
But you still need to keep up with your project that still has
to do with the JavaScript and HTML.
OK. So, first we're going to recommend some books.
David always recommends this one.
You're going to want to make sure that your book is
up to date with all the new iOS versions.
So iOS 7, it was a very recent development.
We are only going to be be dealing with iOS 6,
plus I think iOS 7 isn't
like officially available for couple of months.
So, iOS 6 is what you're going to want to be using.
When you start going back versions of iOS,
things start changing pretty significantly.
You don't want to go back to like iOS 4 before
because things are going to be substantially different.
So, look for iOS 6 things.
Another book that I've never looked at
but is supposedly also pretty good is this one.
And I added this slide just before
because this is one the actually use just
to catch myself up with everything.
It's a pre-preview of a book and I found it to be pretty good.
I feel obligated to say like he does at the top of the page
like if you find it useful you might want
to consider actually buying the book.
But that pretty much everything is in here.
OK. So before we get into Objective-C, you first need
to touch on C. So, it's important to remember
that Objective-C is a proper super set of regular C.
So like any Objective-C program that you write,
you could write valid C all throughout the
Objective-C program.
We're not literally everywhere.
But everything you know
from C is still applicable in Objective-C.
So, first, show of hands, who know C or any C?
All right, that's better than I was anticipating.
And another show of hands, who has any experience
with any object-oriented language?
All right.
Cool. So, we'll do a really quick intro to C just
to refresh you on everything.
You'll probably recognize that a lot of it is pretty similar
to JavaScript, so probably still pretty fresh.
So, your very standard "Hello World" program.
What does hash includes, standard IO.H2.
What is standard IO.H?
[ Pause ]
I Think I might have heard someone say.
But it's a header file.
It literally just contains like--
we'll see like the declarations of the functions.
So we'll see more examples of those later.
Those are still going to be pretty important in Objective-C.œ
Here we see, we are declaring a main function.
So just like in C we declare a main function,
in Objective-C you are also going to have a name function.
And what are these guys, int argc and con char star argv?
What are those?
Command line arguments.
So int argc is how many arguments were passed
at the command line and con char star argv are--
what those arguments were.
And then we just printf, will be--
we'll see that once we got to Objective-C.
We're not going to be really using printf anymore,
but pretty standard program.
So statements-- that is a statement.
Variables, you just declare them int n or say int n equal 0.
That's going to be the same when we get to Objective-C.
We have all of our regular primitive date types, char,
double float, int long, and then the modifiers like unsigned int
and unsigned double, and printf.
So, if we-- let's go into--
We'll have a whole bunch of example programs up.
And we have a whole bunch in C and Objective-C.
We're not going to go through all of the C ones because a lot
of them will just be tedious.
But if you feel you need a refresher, you can just go back
and look at all these.
So, we'll look first C one, hello C.
[ Pause ]
OK. So, this is what we just saw before up there.
And printf, remember,
takes these modifiers such as percent S.
[ Pause ]
That are going to then be a comma separated list of things
at the end of the printf call that you're going to fill in.
So like percent S, it's expecting a string to fill
in that percent S. And if instead we did int n equals 50,
then we could do percent D and pass in the variable N.
So that's how we're going to use printf with--
that's how we print variables.
And you'll see that these format specifiers just percent S
and S percent D for integer.
Those are going to carry over into some Objective-C areas.
[ Pause ]
Plus, all of these primitive data types, remember,
that Objective-C is a super set of C, these still exist.
[ Inaudible Remark ]
Yeah?
>> Do we still we have link to the book, the increment book?
[ Inaudible Remark ]
>> The slide will be online later.
But if you want to look it up now--
>> Thank you.
>> Yeah. And feel free to stop me at any point with questions.
[ Pause ]
It's good.
Oh, yeah. OK.
So the Boolean expressions, the very simple ones
that you should-- all be used to at this point.
Conditions, we have a regular if-elses.
Loops, we have for loops.
So in JavaScript, you also have the, like, for in.
You'll also see that in Objective-C.
Regular C doesn't' have that.
So we have a regular for loop,
regular while loop, regular do-while.
And all of those will still be usable in Objective-C.
So, casting is an interesting case where it's exactly the same
between C and Objective-C.
You're going to see, you might be needing it a lot more once
you get to Objective-C.
So, in C, there are only so many cases I can possibly think
of where it wants a cast.
Like one example is if I want to do like 3 divided by 5.
You know, how like if we just do the integers then 3 divided
by 5 is going to be 0.
So I might want to cast 3 to a float so that it actually does
like floating point division.
So that's one scenario I can think of where I want to cast.
Once we get to Objective-C and we start dealing with classes
and things, then we're going to want to cast like we'll see more
of this but like supertypes to subtypes
and subtypes to supertypes.
So casting, you'll want to be comfortable with it.
And then Pointers, they won't be as important in Objective-C
but you're still going to have to deal with them.
So, we have just the type of a pointer--
let's actually look just an example.
[ Pause ]
All right.
We'll go over the typical example of a swap function.
[ Pause ]
That's here.
Oh. So this line, like, hint
to that before is swap line is the function's prototype.
So those are the sort of things that we'll see in header files
like standard IO.H. We'll also see like struct definitions.
We'll get to structs.
We'll see hash define things.
So, here in main, we declare variable X and variable Y,
and then we print X, print Y. And now we want to swap X and Y.
So ideally, after this swap line, X will have the value 1
and Y will have the value 0.
They will have swap values.
And I won't actually run it.
But trust me when I say that this will not succeed.
Looking at the actual swap function, we see it takes A
and B, so we're passing X for A and Y for B. We then store A
in a temporary variable, put B into A, and put the original A
into B. So, why this doesn't work is it's important
to remember that everything in C
when you pass its way function it's always a copy
of the thing being passed.
And so here, what we're actually passing to a swap is a copy
of the value 0 and the copy of the value 1.
And so down in the swap function when we say A equals B,
we're just modifying the copy of those values.
We're not modifying the original X and Y. So here's
where pointers become important.
[ Pause ]
So, here, notice the function prototype is changed.
We now are passing int star A. So as soon as you see int star
or char star, anything star,
you know you're dealing with a pointer.
And it's coming down here.
We're no longer passing X and Y. We're passing ampersand X
and ampersand Y. So ampersand,
I usually read literarily as address of.
So we're passing the address of X and we're passing the address
of Y. And so-- Oh, and it's-- since X is an int,
then when you get the address of an int,
the type of that address is an int star.
We had a char and-- with an ampersand before it,
then we would have a char star.
So coming down into the swap function, again, this is going
to take an int star and an int star.
And here, it's unfortunately somewhat confusing
that there are two uses for the star.
The first use for the star is
to declare something as a pointer type.
So when you see int star B,
you know that B is a pointer to an integer.
When you do not see a type, like right here, when you say star A,
we are de-referencing that pointer.
So if B points to Y and A points to X,
then star A is referencing the original X. And so temp is going
to store the original value of X. Star A equals star B,
we're going to go to the original value of X,
like the original X and we're going
to store there the original Y. And so,
X is actually been changed now.
And here, we're doing the same thing.
We're going to Y and storing the original value of X. Questions?
[ Pause ]
OK. So, in Objective-C, a lot of this is going to be--
you won't be needing to do as many explicit de-references.
But it's important to remember
that when you're passing these things
that object themselves are pretty much like pointers.
And so if like you're passing object to a function and in
that function you modify the object,
the original object will had been modified
and we're going to see that.
[ Pause ]
And just for fun, I threw in the end
that char star star is also an example of a pointer.
It just happens to be a pointer that points
to a pointer that points a char.
So a good example of that is just our command line arguments,
argv.
So, ignoring the fact that it's bracket syntax, there are some--
this isn't entirely true.
But in a lot of scenarios,
arrays and pointers are pretty much equivalent.
So con char star argv bracket, we could have also said
as con char star star argv, which makes sense
since argv is an array of strings
and we represent a string as a pointer to a single character.
Questions?
[ Pause ]
OK. So, structs, so it'll be important
to actually remember structs
because you will still be dealing with them in Objective-C
and a lot of the iOS code will be dealing with some structs.
Unfortunately, it can be somewhat confusing 'cause you
might forget when you're dealing with a struct versus an object
since they are different.
But let's look an example of using a struct.
Remember, struct is pure C and objects are Objective-C.
[ Pause ]
[ Inaudible Remark ]
Yes.
[ Inaudible Remark ]
So you can.
Once we get to Objective-C, you can, yes.
It's-- A struct is literarily just a wrapper for a--
like a group of variables.
So you're going to have a variable point
to an object then you can store that variable
in a struct just as well.
Looking at a struct example that doesn't use objects.
[ Pause ]
We see here this typedef struct student.
So the only reason for the typedef is so that--
[inaudible] technically it's a student here.
But the only reason for the typedef is
so that whenever we want to declare a variable
of this struct type, if we just do this, now we have to say,
struct student X and struct student Y.
So the typedef just saves us that.
And now I can just say struct student--
or now we can just say student X and student Y.
So what is inside of this struct?
We have an age and we have a name.
And so, these are exactly what structs will look
like in Objective-C.
And coming down here, we see we declare a variable
of this struct type, Alice, and we're going to use .notation
to access the fields in that struck.
So, Alice.age equals 20 and Alice.name equals Alice.
And we could do the same thing, we just declare Bob
and that's pretty much like everything
about Structs that you will need.
So, questions?
Oh, and then if you want, look at degree [phonetic] function.
Up here we are storing inside of Bob at age 21
and down here we are accessing Bob.age.
OK. Next, we will also have enums
which are somewhat more important in Objective-C
than they were in-- perhaps you've used in regular C
since there's a lot of the-- a lot of code you'll be working
with uses a lot of enums.
So, what does an enum look like?
So, it's like a struct and again we're just using typedef so that
when we want to declare a variable
of this enum type we don't have to say enum genders X
and enum genders Y. Thanks to the typedef you're going
to say genders X and genders Y. So,
enums aren't strictly necessary.
We could instead do hash define female as 0
and hash define male as 1.
And hash define just declares this to be a constant.
So right now, if I got rid of this,
the two programs will be almost equivalent except for the fact
that I just got rid of the genders type.
So, why do we prefer enums over these hash defines?
Because if I add a whole bunch of hash defines something two,
something three, something four and then I decided
to like, reorder them.
Then I would have to like change the numbers on all the rest
of them and also it's just a convenient that I don't have
to explicitly list the numbers on all these things.
Once we get to Objective-C and I think more specifically Xcode,
there's also some-- well, it's coming down here.
We see that we have changed this struct to now not--
or now it takes a name and a gender.
So, Alice is going to be-- is going to be given the name Alice
and it's going to be given the gender female.
So, it's important to remember in C and also Objective-C
that there is no enforcement of the gender's type.
So, I am just as easily able
to put a hundred underneath the hood
and enum is literally just an integer.
So, even though a hundred is not a valid genders,
it will let me do this.
But in Xcode, generally it will--
it will yell at you like visually if you're using things
that aren't correct enum types.
So, you'll wan to use these enums correctly.
And that's pretty much it for enums.
Questions?
[ Pause ]
OK. So then, arrays, regular C arrays are still going
to work in Objective-C.
You're also going to see
that there are these new array classes
that you're probably going to want to get used to.
So, you might not be using them that much.
Just to look at an example of using the arrays.
[ Pause ]
So, here we declare the variable int 10.
We print enter number of exams and then scanf is just a way
of grabbing input from the keyboard.
So here we are scanf'ing for some integer,
this percent D carries over from printdef.
It's looking for an integer.
And why do we need to--
why do we need to pass ampersand N and not just N?
Why would this never work?
[ Pause ]
[ Inaudible Remark ]
Yeah. So inside of this scanf function,
just like we saw before the swap function,
ideally after this point in time N equals whatever number I type
at the keyboard.
So, scanf needs to actually change this N. Scanf can't
change that without a pointer to that N,
without having the address of that N. Otherwise,
if I just did this and we'll first do in compile.
But assuming it did accept that, it would just try
to set the local variable N to the keyboard entered value
and this N would remain unchanged.
So, we need to pass the address.
Here we are declaring an array and that array is going to be
of size N. So we're going to have N integers.
And this is all going on the stack so far.
And then we're iterating over the N values entering a grade
into each individual spot in the array.
So really, this program is going to behave
like how many grades you want to enter?
Three. What is the first grade?
What is the second grade?
What is the third grade?
So, you enter each grade.
And also we have to-- So grades I is the Ith position
in the array and then we also need to pass that by reference.
We need to pass the pointer to grades I for the same reason
that we needed to pass the pointer to N.
[ Pause ]
Questions?
[ Pause ]
OK. So, memory management.
It's one of the bigger problems in C and for the most part,
you are going to have to deal with it in Objective-C.
There are some small things you'll have to think about
and we'll get to that next week.
But the malloc and free stuff that you're used to,
you don't really have to deal with.
So, remember that we have our stack and our heap.
And so all of our local variables are always stored
on the stack.
And this means, let's say I call some function and it needs
to like return some array to the function that called it.
It can't just return-- it can't just return an array
on the stack and return it,
because once the function returns that array is gone.
That's the point of it being a local variable.
The array is gone.
So, malloc, what that does, is allocate space on the heap
and the stuff that out--
that's allocated on the heap survives past whenever the
function happens to end,
whenever that variable happens to go out of scope.
And so what malloc and free are like manual memory management
versus the automatic memory management of local variables.
And something to keep in mind is
that pretty much all objects are going to be like this.
All objects are going to pretty much be malloc.
They're going to go on the heap.
And so they are going to continue existing
after the scope of that variable ends.
But thanks to the new iOS Objective-C features,
you don't really have to think about freeing that memory.
So we'll see why that's really useful.
[ Inaudible Remark ]
Yes. So, the new-- it's ARC,
A-R-C is Automatic Reference Counting
and it will automatically collect these objects for you.
That was not the case two or three years ago.
Yeah?
[ Inaudible Remark ]
When you don't want to use ARC?
So, the only thing I could really think of is
like if you wanted to be really explicit about the--
like you want to fine-tune your program, overly optimize it
to make it like run better.
But that's probably not the beast use of your time.
It's-- You are already using Objective-C
which there are a lot of things that that's not doing
in the most optimized way possible.
So, pretty much any app nowadays is going to use ARC.
[ Inaudible Remark ]
Oh, so an example--
[ Inaudible Remark ]
It probably would.
But it's not really worth even trying
to optimize your app for that.
[ Inaudible Remark ]
Yeah.
[ Inaudible Remark ]
No, it will not.
You pretty much shouldn't be malloc'ing.
I actually wonder, I'm not a hundred percent sure,
but I imagine it's already taking very strict control
of what the heap looks like.
And so, if you start malloc'ing things on top
of what it's trying to do with the heap,
it might screw it up but I'm not sure.
You won't need to malloc.
OK. Objective-C.
So C questions before we move on to Objective-C stuff.
Yeah.
[ Inaudible Remark ]
Oh. So that's-- Well, in C you would need to use free.
So anything you malloc, at some point during the life
of your program, you should also free.
In Objective-C, that's the thing so things are going
to be somewhat automatically allocated for you
and they will be automatically de-allocated for you as long
as you adhere to some things we'll see next week.
OK. Any other questions about C before some Objective-C stuff?
OK. So, from our Hello World in C to our Hello World
in Objective-C, there aren't too many changes.
You'll see that it looks a lot like C in a lot of ways.
Unfortunately, the first word has literally changed.
So what do you think the difference is between include--
like we used to say hash include, now we say hash import.
So what do you think the difference is there?
[ Pause ]
So hash import is smarter than hash include
and that it will only import something exactly once.
And so, this used to be an issue with hash includes
like if you hash include a header file twice
and you don't take special precautions in that header file,
then you might duplicate some definitions
of things and it won't compile.
Hash import, no matter how--
if I said hash import foundation dot--
or like if I just copy and paste this line,
the second line wouldn't do anything.
So, hash import just going to be more efficient in that.
And the-- another thing
that looks somewhat different is this @autoreleasepool.
So that's going to be something we deal with next week.
That has to do with automatic memory management.
And the one thing to note and we'll also see it in front
of the Hello World is @ is a very Objective-C thing.
So like if you see code and you see an at symbol,
you might be able to reason
that it is Objective-C 'cause you're going
to see this all over the place.
In case of the Hello World, so normally we would see just
like string hello world by putting the at symbol in front
of it, we are making it an Objective-C type string.
More explicitly we are making it an NS string.
So we're going to see that in a couple of other places.
But now this-- this at hello world is an object
that we are passing to the NS log function.
Let's actually run that.
[ Pause ]
So what is the ridiculous--
and so you will pretty much never need
to compile at the command line.
Because once we get into Xcode, that's going
to pretty much be everything you need.
But here, we have compiled that program.
It's exactly the same as the one that we saw in the slide.
And running it, we see something that looks like this.
So, we see the date, we see the time, we see main
and then this happens to be the process ID
and then something called the "Mac Port" [phonetic]
that you don't have to care about at all,
and then the actual thing that we NSLogged.
So, this is what NSLog does.
You will probably be using NSLog pretty frequently
in your programs to debug things.
In actual released apps, you probably want to get rid
of your NSLogs or have them wrapped in, like,
debug type statements.
Since-- Once you're on an iPhone,
you pretty much don't have access
to anything that is NSLogged.
I think theoretically, you can like plug in your iPhones
to your computer and see what was NSLogged.
But that's rare.
Like, anything released
to the App Store isn't going to have any of those.
[ Pause ]
OK. So this is our first exposure to an object,
but it doesn't really feel
like an object 'cause we're pretty much putting
that sign in front of it.
That's technically shorthand for creating a string object.
And we-- I think we'll see the longhand later
or at least see many other objects
that we're going to be creating.
So, use those signs that just says everything
so far has been the command line.
Everything can be done at the command line.
You probably won't want to do things at the command line.
So, Xcode is pretty--
pretty comprehensive on all the things Objective-C in iOS.
You should be able to get it for free and we aren't really going
to go into the details of what all these different places
in Xcode are.
It's pretty overwhelming the first time you see it.
The only things we're going to be using today, like--
it's going to look like three of them.
So, we're not going to be using utility area.
The debug area is where we're going to use to see
where NSLog things are going to be printing.
The editor area is where we're going to see our code.
And navigator area, we're just going to see our files.
And it also contains all this debuggings, important stuff,
but we're not going to go into that.
So, you could-- if you have an iOS device and you want
to actually install these apps to your iOS device,
this was discussed last week.
But you need a developer account.
So through us, you can get a free account.
But you are not able to actually put the things on the App Store.
So if you want to put things on the App Store, you will want
to get your own accounts which is 99 dollars per yourself
and I think like 2.99 for a company or something.
So, you're going to look up a lot more there
and this will be put online later.
So, the new data types in Objective-C,
there is pretty much only two big primitive data types
that you need to care about, so BOOL and ID.
So, a BOOL is like a BOOL in every other language.
Unfortunately, it is not true and false.
It is yes and no.
So you're going to be seeing a lot of capital,
yes's and capital no's as in your programs.
I think the reason for that is once we started seeing
functions, the way the functions are awarded,
it's kind of like-- and do you want this?
Yes. And do you want this?
No. ID. So, if you're more familiar with C
and you know what void star is,
ID is sort of like that but for objects.
ID just sort of represents like a generic object.
You don't know what the type of the object is, but you know
that this thing is an object.
And nil is sort of the counter point-- counterpart of null.
So nil represents a non-existing object
but it has some special properties.
Questions?
OK. So here are some data types that if you saw
when we hash imported foundation slash foundation dot H
which pretty much everything you're going
to be doing is going to do.
We also get some of these data types and as integer
and as point and as rect.
These are not objects and this can be somewhat confusing
because it can be somewhat difficult to differentiate
between objects and just these typedef things.
So, they exist for various, like, legacy reasons and so,
like, NSInteger exist as sort of this weird bridge between 32 bit
and 64 bit and pretty much use it whenever like--
when you're looking at documentation and you see
that this function returns an NSInteger,
use an NSInteger variable.
So, none of these are object types.
Now, just a quick discussion about what classes
and objects are in case you don't have any
object-oriented experience.
So, we're going to be defining classes today.
And a class in-- It's going to be similar in Objective-C
to other languages you've seen.
A class is going to define methods and variables
and it's pretty much a blueprint that then objects, you're going
to create from those classes.
So a class is going to say like any object
of this class should have these variables and these methods.
And then it's on those objects that-- or in those objects,
you're actually going to have those variables.
So, you have a single class and many, many objects can come
from that single class.
It's also important to remember
that in object-oriented programming, classes,
you're going to have this hierarchical relationship
that we're going to be seeing.
So like if I define-- Well,
in Java you might have seen like the objectClass.
In Objective-C, the equivalent is NSObject.
So, everything, almost everything in some way inherits
from this NSObject class.
And so-- so if I defined some class, person that inherits
from NSObject, then I might define another class,
student that inherits from a person
and then I might define some other class,
8th grader that inherits from student.
So, remember that these classes have these
hierarchical relationships.
And this is important when you're looking
through the documentation because if I look
at some random-- like, if I look at the Apple documentation
for the 8th grader class and it shows me, like,
the method spelling homework.
You might think that's the only method it has,
but it has a lot more methods than that
because it's also inherits all of the methods from all
of his parent classes.
So, you need to look through the hierarchy
to know all the methods everything has.
Question? OK.
So, .h files.
Unfortunately, the interface keyword is somewhat different
from what you might think of as like a Java interface
and some other languages interfaces.
It's still similar and that you're going to be defining
like you're just going to list the prototypes of the methods
that you want to be in this class.
But we'll see later this thing protocols and those are going
to be more like the interfaces you're used
to in other languages.
So in .h files, we see-- we have this @interface,
and so @ as usual telling us it's Objective-C.
So @interface and this class is going to be called foo
and then this colon indicates the class
that we are inheriting from it.
So our parent is going to be NSObject.
And then this ugly syntax where we put curly braces
and then instance variables go in the curly braces.
And then underneath the curly braces,
we declare all the methods that this class needs to define.
And we'll see plenty examples of those.
And then getting into .m files.
So pretty much every .m files is going
to have its corresponding .h file.
Inside of the .m file, we give the implementation
of these things.
And so here we're going to give the implementation of foo
and actually define all the methods
that in this .h file we said we would define.
OK. So we'll look at an example.
And this time we'll do it in the next code.
Actually.
[ Pause ]
All right.
So, here we see on this left side, we have our files.
I'm going to get rid of this right side 'cause we don't need
it now.
Up in the-- or down at the bottom,
we're going to have our NSLogs stuff down here.
So looking through these files--
I'm not going to be able to do that.
So looking to these files and we see-- we have a main function.
We have the same AutoReleasePool thing
that you can ignore for now.
And then we're going to have these student star Alice.
So, student we see over here is going to be an object.
We have .h file and .m file for it.
We'll look at those in a second.
Student star, so I guess I'll go into that.
Ignore this for a second.
So, just student star Alice,
we're going to allocate the student.
So this is sort of like malloc.
So, we're making broom for the student.
And then apparently, we have some age field
and some name field.
Let's actually look at it.
So here's student.h. And we have interface student,
it's inheriting from NSObject.
And here we see this @public keyword.
This tells us that everything underneath that--
all the variables underneath this word are going
to be public instance variables.
There's also app protected and app private.
So private, no other class is going to be able
to see these variables and protected any class
that is a subclass of this class is going to be able
to access these variables.
So you won't need to deal with those too much.
Generally, you want to make the access
to these variables as tight as possible.
So like if the variables can be private, make them private.
So here, the instance variables we have are age and name
which is an NSStrings star.
And we see since there are no methods defined down here,
that means that, well,
let's look at it student.m doesn't need define any methods.
Yes?
[ Inaudible Remark ]
Why do we use what?
[ Inaudible Remark ]
Oh, so, we could use string or just char star
like a regular C type string, but in Objective-C, you're going
to be passing around these NSStrings a lot.
So you're probably going to want this thing to be an NSString.
Like when we want to actually print this,
we're going to need print an NSString.
We can't-- Oh, when we want to NSLog something,
we need to NSLog objects.
So we're going to need to pass it in NSString.
We can't pass it a char star.
We would have to change that char star to an NSString.
>> But we also got NSInteger [inaudible].
>> Yeah. So, NSInteger is-- this is where it's--
NSInteger is pretty much going to be just a typedef
for regular int or possible long.
This is not an object type.
This is not a class.
This is just like typedef, NSInteger, int.
So, this why like-- these aren't that helpful unless you see
that a function
in the documentation is returning an NSInteger.
And then you should use NSIntegers.
[ Inaudible Remark ]
Yes. So that's the unfortunate thing.
You got pretty-- like the primitive ones are these NS--
well, actually no, I can even say that.
There are some complicated ones that are primitive
and I wish they had done something
to differentiate better, but they didn't.
and let's change back to NS, but it shouldn't change anything.
So, it mean-- So we are now accessing this.
So student star Alice is an object.
That object has an age field and a name field
and we are accessing those and setting the age field to 20
and we're setting the name field to be this NSString Alice.
Note that this would not succeed without the @
because now it's not an NSString
and it yells at us appropriately.
And in case you're curious, this arrow syntax, it comes more
from C, come-- the next example that I gave you,
you will not be using this arrow syntax.
But what it is, is-- so,
we're treating Alice sort of as like a struct.
And so, we are de-referencing that struct
and then accessing the age field inside of that struck.
So, arrow is equivalent to star Alice dot.
It's-- This to just say very disgusting syntax since,
that's why they give us arrow.
Arrow just means, here is a pointer to a struct/object
and go to that object and change this field at that object.
But you will not be using arrows on objects ever.
So, this is a pretty bad example,
but this is our intro example.
Do the same thing with Bob, we allocate
and we give him an age, we give him a name.
And then greet [phonetic] down here.
We're going to NSLog and we see NSLog and we need to pass NSLog
and NSString as its first argument.
And so we see our normal percent D over here and as age is just
as we saw in the student.h file, as age is just an int.
And so that's fine.
And as name was an NSString.
And so, the NSLog version of like percent S
for NSStrings is going to be this percent @. So,
that is the flag for printing NSStrings.
Actually running this, on top, hitting build or run.
I forgot the shortcut for it.
And down here we see the NSLog output.
Hello Alice, you're 20.
Hi Bob, you're 21.
Questions on this simple example because it's going
to be changing pretty substantially
in the next example?
[ Inaudible Remark ]
Yeah. So, this is also what I kind of pause
at before 'cause I don't want to say quite yet.
Student star, student is really like--
Alice is the object but like pretty much read student star--
don't read that as a pointer to a student,
just take student star to be like the type of the object.
So, you will never really be dealing with a student Alice.
You will always be dealing with a student star Alice.
And in the next sample, going to students to--
[ Pause ]
[ Inaudible Remark ]
No, not really.
[ Pause ]
OK. So, in this example, let's look at .h first.
So now, this is the same, it's inheriting from NSObject.
We have changed this.
We're no longer saying int age and NSString name.
We're saying underscore age and underscore name.
And that is a convention that in the past it used just
to be a convention and now it's a convention
that actually mean something.
So you're going to want
to pretty much always have these instance variables
be underscored.
And now, here we're getting
to these strange looking method things.
So, let's actually go back to slides for a second.
[ Pause ]
[ Inaudible Remark ]
We'll see in a second why we want the underscores
and I quite gotten there yet.
OK. So instance variables, we saw,
we know them @protected, @private, @public.
And it's somewhat messy.
But like when I said @public,
everything beneath the @public would be public.
But then if I switch to-- like if I @public int X
and @private int Y. Y would be private 'cause it's underneath
the private.
OK. So, first let's look at this.
So, messages.
In other object-orientated languages,
you don't really-- well, some you do.
But Java, you don't.
So, messages are going to be the way that we invoke methods
on objects and classes.
So here, this square bracket syntax is what you're going
to be using to send messages.
And here we're saying,
the student class has a method called "alloc."
And so, send to the student class that method.
Invoke that method.
And then that is supposed to return a student star.
And so this alloc is going to be pretty much everywhere.
You-- Whenever you need to allocate an object,
you need to do some sort of alloc.
Sometimes, there is like alloc,
sometimes there are some other alloc type function you might be
using, but you're almost always going
to be alloc'ing these things.
So, here-- So there are two different types of methods
like there are in other object-oriented languages.
So we have instance methods and class methods.
And so, the way we're going to differentiate
between those is all the way on the left side,
you see we have this minus sign.
So, if we have a minus sign that means the method is going
to be an instance method.
And if we have a plus sign that means
that it's going to be a class method.
And an instance method is something
that you actually need an object to use the method
and a class method is something
where you don't need an object to use the method.
So going back to here, the fact that we're calling alloc
on the student class tells us that alloc is a class method
because we don't actually need a student to allocate a student.
That'd be pretty flawed if we couldn't actually get a student
without having a student.
[ Inaudible Remark ]
Yes. So, yeah.
The static keyword from Java is the equivalent of plus.
So the syntax for these things, we see all the way
in the left is going to go plus or minus always.
And then we're going to have the return type of the method.
So here we have void, int, void.
Then after return type, we have the name of the method.
And so we have the name init and we the name age.
And then technically the name
of the last method is going to be set age colon.
We'll see why.
But this here-- this age is what we're just going
to call that variable.
And this is the type of that variable.
So, this method isn't going to return anything.
It's called set age colon and we would pass it some integer.
[ Pause ]
So, sending those messages, we see that student--
we're using lowercase student, so the student over here,
the student object, since these are instance methods,
we need to send these messages to objects.
So we send the init message to student.
We send the age message to student.
And then we sent set age
with the parameter 20, with the argument 20.
Questions?
[ Inaudible Remark ]
What do you mean?
[ Inaudible Remark ]
>> Yes. That is how you should call it.
[ Inaudible Remark ]
Could you call as what?
>> Like I would in C.
>> How would you call it in C?
>> I mean is that like I would say C and then like that?
>> Oh err-- so no.
This is why the previous example is something that was bad.
You should very barely be differencing objects.
I almost want to say never difference objects.
And so, the arrow operator is n implicit difference.
And so init is also somewhat different
from setting the fields of the object.
And another reason why the previous example was bad,
you always-- you never want to deal with an object
that was allocated but not initialized.
So, even though the student objects, and we'll see
in the next example how--
how originally just had like student alloc
and I did Alice arrow age.
I shouldn't have done that.
I should have done student alloc init.
So always initialize your objects
and then I could access those fields.
But then on top of that,
I shouldn't be accessing those fields using arrows,
I should be sending messages.
And so we'll see that in the next example,
the right way of doing that.
And then we'll see that there are like 10 new
or right ways of doing it.
So selectors-- pretty much an alternative name for method,
so alloc, init age and setAge colon.
Remember the colon is part of the name?
Once we see multiple argument functions,
we'll see that there will be multiple callings in the name.
So, all of those are just selectors
and we'll see why that's relevant later.
And let's look at that example now.
So student two, OK.
So, here we have said int underscore age
and underscore name.
And now we have for methods and this is like the getters
and setters of Java that you might be used to.
We have two methods, one called age and another called setAge
that the first one is going to get the age of the thing.
And the second one we're going to use to set the age.
And then similarly down here, we have name and setName,
the first we're going to use to retrieve the name
and the second we're going to use to set the name.
And these are important names both by convention
and we'll see things that help us later
where in other languages you might say
like getName and setName.
Here, the convention is just to say name.
Do not say getName.
Questions?
OK, so looking at the implementation,
we must be implementing these for methods.
And so, notice, they are all instance methods,
they are all minus.
And age, we'll just going to return underscore age.
And setAge, we're going to set underscore age.
So we're going to set our instance variable age
to the pass in argument age.
We're going to return underscore name and we're going to set,
and this one is somewhat interesting.
So, we're going to set our instance variable underscore
name to name copy.
So, we know that this in fact is how we're going
to send message to objects.
Name is in NSString object.
And so, apparently and you can look it up--
you can look in the documentation to verify this.
Apparently name or NSString has an instance method called Copy
that is going to return a copy of this NSString.
And why do you think we want a copy of the NSString instead
of just saying underscore name equals name?
[ Pause ]
Yeah.
>> Well because it's an object,
it should be modifying the pointers of that object
so it would be modifying the initial objects.
>> Yeah, so it isn't-- well actually, so,
if we did not make a copy of the name, it isn't a thread
that we are going to modify that NSString
since we don't have any methods for modifying that NSString.
I guess we-- if we went around the proper method protocol,
we would be doing things.
We'll see why we should never be modifying name.
But it's possible that the NSString that was passed
to us @Bob or something is that--
that could later be changed.
And so if that is changed then if we just do this,
then we are also going to--
the name within this object will have been changed.
So we want to copy Bob for ourselves in case
if Bob has ever changed, we don't want to be changed.
[ Pause ]
OK, so looking at main.m [phonetic],
now this is the better way of doing this.
This is like appropriate objective-C.
We can see that there are more and more better ways but this is
at least like not bad.
So, we are appropriately initting and notice
that we are allowed to like nests these things.
So, we could if we wanted do student alloc
and then Alice equals Alice init,
but we are allowed to nests these calls.
OK and now we are, instead
of directly doing Alice arrow age equals 20 which is bad.
We are saying Alice setAge to 20.
We are sending the message setAge with the argument in 20
to Alice and we're setting the name to Alice
and similarly with Bob.
And then what greet [phonetic] is going
to do is use this S name and S age.
We're going to send those getter methods to get getter messages
to get the appropriate instance variables.
Yeah.
[ Inaudible Remark ]
Oh so, the only reason we can do that here is
because student alloc happens to return the student object.
And so we are then using that student object and initting it.
And that also returns the initialized student object.
SetAge doesn't return this student object.
If we do we could actually do that we can do like instead
of void, we can have it return the student object.
[ Pause ]
>> And then this is going to get into return self.
Self is going to be your keyword here.
We'll see it later.
[ Pause ]
[ Inaudible Remark ]
So here, are you saying why should we need--
[ Inaudible Remark ]
So this is that you never pass but--
you never pass objects by value.
You never handle objects as explicit values.
You're always going to go through a pointer to the object
which is why I say pretty--
think of like NSString star
as the object not a pointer to the object.
Think of it as the object.
Except that if you modify it, then it's going to be modified
because it's a reference.
OK, so now we're returning self which is going
to allow us to do that nested.
Now we're free to do Alice setAge 20, setName Alice.
[ Pause ]
[ Inaudible Remark ]
We-- not yet.
The next example we'll be able to.
Just to point out one other thing that you might see
in like documentation or like example online or stuff.
So alloc init is such an incredibly common thing
like you alloc init-- you might be doing some
different initializer.
There are different initializers but using alloc and init is
so common that there's actually a shortcut--
[ Pause ]
-- New, and so, new is going to sort of--
or new is going to first allocate and then initialize.
So that does it in one step.
There are sort of-- well, this is the first
of three religious wars you'll hear today about objective-C
that there are a lot of people
who will say new is a perfectly fine thing, and there are lot
of people who will say you should absolutely never say new.
So, we don't care which you use, whether you want
to explicitly allocate and initialize or whatever.
[ Pause ]
OK? Questions on any of that?
Yes?
>> So does allocate initially reserve space on the key
for the object and then setting
on the instance variables on that?
>> Yeah, it is-- potentially other things
than setting instance variables.
If you wanted, you're going to find the initialization method
that like counts the number of objects of this type
that had been initialized.
But you should never handle an uninitialized object.
[ Pause ]
OK? So then this is going to be the next example
that we're going to want to use
but let's just look at the slide first.
So, Property so-- and this is going to be what we're going
to use to enable us to use .syntax.
We can somewhat ignore a lot of these keywords for now.
These assign, copy, strong, weak are things we're going
to deal with next week.
Strong and weak in particular are pretty much the only things
you really need to think about under ARC.
Those are memory management difficulties
that if you got those wrong, you can still leak things.
But it's not too bad.
It's especially better than needing
to keep track of everything.
Atomic and nonatomic are a different pair of things
that we'll get into and we don't mean readwrite.
We will talk about today.
So @property, new thing.
So look at the example.
[ Pause ]
Student-free.
[ Pause ]
OK. So looking at student.h, the only thing that is changed is
that we have added these two lines.
So, we have SetAppProperty and from each of those groups
that we saw in the-- on that property slide,
we are picking a sign from the first group, nonatomic come
in second group, and readwrite from the third group.
And then we're saying that this instance variable is called
int age.
So, assign again, you can ignore nonatomic.
This is just saying that like you can assume
that we're not dealing with any multi-threaded type
messiness here.
You don't have to deal with the overhead of making sure
that whenever we modify this age instance field
that you don't have to deal with making sure it's atomic.
So atomic just means like it happens instantaneously.
We don't have to deal with that.
So, and readwrite, this is probably
or in this class you're pretty much only going
to using nonatomic.
Readwrite is one that if it's readwrite then this property is
expecting a setter and a getter.
If it's read-only, it's expecting just a getter.
So since we want to be able to both write to age
and get the age, then we say its readwrite
and some it will lead for name.
OK, so then these are the same.
Back in student.m we see the same.
But looking at main.m, the fact
that these are now properties allows us
to say Alice.age equals 20 and Alice.name equals @Alice.
So what do property does for us is says
that since we said there is a property called age then
Alice.age is by the conventions that are now going to be
like something you should absolutely follow,
Alice.age is underneath the hood going
to be translated to Alice setAge 20.
And this is going to be Alice.name @Alice.
So this is what properties have done for us.
It's allowed us to access
and set instance variables using .notation.
Instead of having to go through this set name
and setAge method or message passing.
It's somewhat important and yet at the same time not really
that important to remember that we are going
through the overhead of a message pass.
So it's not like in regular C, this is not a struct,
so you would not be able to use .notation
on a pointer to a struct.
This is an object, this .notation is calling a method
and so there's some overhead to that but again its Objective-C,
let the compiler handler--
let the compiler handle any optimizations.
Don't really worry about the overhead of message passings.
Then down here at greet, we see s.name and s.age
which are equivalent to just S name and S age.
And so this is why I said before,
you should follow the convention
that like the getter is just called name and not getname,
because s.name is going
to expect the getter to be called name.
And if it's not, you're not going to be able
to use the property as expected.
[ Inaudible Remark ]
Wait till the next example.
[laughs] Yeah.
[ Inaudible Remark ]
I changed that.
They should always have it.
Yeah. [Inaudible Remark] So the reason for this is
that NSObject's init method, so init is inherited from NSObject.
And we see that Student is directly inheriting
from NSObject and so because the init method
of NSObject does nothing, then there is no difference
between Student alloc and Student alloc init,
those two things are going to be the same.
But you should always handle initialized object if--
I doubt NSObject would do this,
but if someday NSObject changes initialize method
to now keep track of something, then this code will break
because you did not initialize that object.
Or alternatively, if inside of Student,
I decide to overrride the init method and have it do something,
define my own init method,
we'll actually see examples of that later.
But if I were to define my own init method,
then all of a sudden, everything in main.m would stop working
because it did not initialize the Students.
So always-- even if you know you're inheriting
from NSObject, still initialize it.
Even if it's because someone later on coming
around reading your code is going to be like, "Wait,
this isn't initialized," now, they have to go check
to make sure that it--
the initialization isn't actually going to do anything,
it's always initialized.
[ Pause ]
So one last.
OK. Any other questions?
[ Pause ]
OK. Then here.
OK. So synthesize, this is what in the past was used
to do exactly what you just said, that getting rid
of the getters and setters.
So, what-- let's look at Student 4.
[ Pause ]
So we have gotten rid of the explicit declarations
of the setters and getters from here, just deleted them.
They were redundant to begin with.
And Student-- or student.m, we've now gotten rid
of the implementations of those things.
In the past, we used init do
like @synthesize age equals underscore age messiness.
The reason for that is because the compiler didn't use
to be smart enough to recognize that if there's a property
in here, then it should automatically be in here.
Now, it is smart enough.
So now, the property is enough to say
that we want an instance variable called,
we're actually using the defaults,
and this is again why we come back to underscore, the defaults
of this line is, we want an instance variable called
underscore age that has a setter called setAge
and a setter-- a getter called age.
And that setter and getter is going
to be implemented using these particular semantics
but you don't have to worry about assign and nonatomic yet.
This also means that before, even though we had set assign,
and nonatomic, and readwrite,
you are allowed to override those.
And so before in the previous example
when we had explicitly defined the setAge,
setAge was not necessarily following these semantics.
It happened to be because that's how we implement it.
We didn't implement it carrying
about whether it was multithreaded
and all that stuff.
So you are allowed to override these behaviors.
I actually think Student 5 might go into that.
[ Pause ]
So Student 5, looking at student.h, again,
we still have age and name.
Now, in student.m, we still do not synthesize
but we just happen to decide to overwrite the setName method.
This was David's example of if the name happens to be David,
then change it to Dummy, otherwise,
do the original behavior.
So here, we have overwritten what the default setting would
do if we just did copy nonatomic.
But, if we also decide that we wanted to--
[ Pause ]
If we decided that we wanted to override the getter,
and say return name, now, because of the way things are,
we do need to explicitly synthesize.
So, now, we would need
to say synthesize name equals underscore name.
And those should go away.
All right.
It's only if you happen to be overriding both the getter
and the setter that we need to synthesize the variable again.
Otherwise, it wouldn't know
that this underscore name variable exists.
This behavior is because of some backwards compatibility issues
but it's the way it is.
[ Inaudible Remark ]
But if you use property and you say readwrite,
if it is a readwrite property, the getter is--
getters and setters are automatically defined before you
unless you decide to override them.
And if you override them both, then you need
to synthesize again, because otherwise it doesn't know
about that instance variable.
It's like looking at student.h, we see property age
and property name, we don't see anything about underscore age
and underscore name, and that's part
of the reason why we need to synthesize.
It's messy but rarely are you going
to be overriding both the getter and the setter anyway.
You might be overriding them in--
if you are like trying to debug something and you add NSLog
to both the getter and the setter, in which case,
remember that now, you're going to need to synthesize or self,
it'll [inaudible] you.
Questions?
[ Inaudible Remark ]
Yeah. See?
It-- well, if I get rid of the assign, now,
I'm going to get a bunch of errors.
If I now get rid of this setter, I don't have any errors anymore,
because as long as I only override one of them, it's fine.
It's also important just to recognize synthesize
because you're going to see it in a lot of prior examples,
like a lot of online things you find will use synthesize,
'cause it's a relatively new thing.
But you don't need to use it.
OK.
[ Pause ]
OK. So, init methods.
So up till now, we just used init.
Remember, you should always initialize something
but you don't need to initialize it with just init.
You can define your own initialization methods.
And if you look at-- well, when you're actually doing iOS,
you're going to be dealing with a bunch
of other initialization methods.
But the convention is that the initialization methods are
always going to start with lower case init, and then, the--
so, reading this method, we have an instance method 'cause it's
a dash.
It's going to return an ID, so this is also convention.
We know that it is necessarily returning a Student star,
and remember that ID is just sort
of like a catch all for all objects.
The convention
for initialization methods is that they return ID.
Then the-- this is pretty much the convention too
that we have initWithName: and we pass it a name.
And notice now, we are passing a second argument,
so space andAge:age.
So the name of this method is initWithName:andAge:.
That name and age are arguments.
Those are not part of the name of method.
So, we already see how these names can get pretty long.
Believe me when I say that there are method names that are
like four times longer than this in iOS dealings
that you will be using.
So, one other-- I don't know.
Questions.
[Inaudible Remark] Yes.
It's very similar to void star except it's dealing
with objects instead of general pointers.
And we'll see ID in other places too.
And it's also similar to voidstar
and that automatic casting happens.
[Inaudible Remark] This whole thing?
OK. So, we have instance method.
It is returning an ID so that's just the way it is.
If you wanted, you could say Student star,
but you shouldn't-- you should say ID
because any initialization method pretty much returns ID,
then the convention is that you're going to init and then
with is also pretty much the convention.
The-- any colon-- you can count the colons
to determine the number of arguments to your function.
So here we see two colons.
That means we know they're going to be two arguments.
The first argument is called name,
and a subtype NSString star.
The second argument is called age, and a subtype int.
So, when we want to actually call this function,
we might say like, well, first, we allocate a Student
and then we say, Student initWithName:@bob andAge:21,
and we'll see an example of that
in another Students 4 or 5 or whatever.
[ Inaudible Remark ]
So, the answer is no, but that should never be the case
because if the variables are different,
this naming scheme should be different.
This is how you name methods in like--
all method names are very long and explicit in Objective-C.
And so, if we decided that instead,
we wanted to just initialize with the name,
then we would have initWithName method without the andAge.
If we wanted to just do name, we would've initWithAge method
without the andName or whatever.
Yeah.
[ Inaudible Remark ]
That was a typo.
That has been fixed.
These will be uploaded at the end.
There are some changes.
Other questions.
Yeah.
[ Inaudible Remark ]
Yeah. You would just put more
with andGender, andYear and whatever.
The number of colons specifies-- in theory, we wouldn't--
we don't need to say andAge like a valid method name is init,
colon, colon which-- because there are two colons,
we expect there are going to be two arguments, and so we call it
with like init:bob:20, but that's not what you should do
in Objective-C, you should explicitly name all
of your parameters.
So, initWithName:whatever, andAge:whatever.
[ Inaudible Remark ]
You cannot by default pass in a dictionary or object or anything
like that, this is pretty much the only way you can run it,
unless you happened to define initialization method
that like takes what we'll see later like in NSDictionary,
but that's up to you to define such an initialization method.
It's-- but you pretty much should--
this is the way it should be.
And also, if you follow this convention,
I'm pretty sure Xcode is going to give you some like--
some more advanced tips in Auto Completion and stuff.
The convention being like they should return ID,
they should start with the four letters, init.
And when someone is reading your code, they expect you
to initialize something so they should see the four letters,
init.
OK. Looking at this example.
[ Pause ]
Six. OK.
[ Pause ]
OK. So, in student.h, we see we are now declaring a new method,
exactly what we saw before.
Now that we have said that we are using this method,
we need to implement that method in the .m file.
So, here, let's first look at the initWithName.
So, this is a very common pattern.
Whenever you define your own initializer,
this is pretty much the pattern you want to take where the--
[ Pause ]
-- first, second-- let's say this first.
So, this is somewhat weird from other languages
where like self is just sort of like a keyword.
Here, self is a variable and you're assigning
to that variable the result of initializing your super class.
So, this is the part of the pattern
that you pretty much always do.
So, just because like--
or I happened to inherit from NSObject
which its initialization method does nothing,
but imagine that it does do something.
So, just because I know how I want
to be initialized doesn't mean I know how my parent class wants
to be initialized.
So, you should always call your parent--
initializer of parent class.
So, the reason we assigned to self and do this whole
if self equals super init thing is under some bizarre scenario
where initializing the super class manages to return nil
or something, like initialization went wrong,
then we don't want to do these two things.
As an example, maybe we just happened
to define the initializer as like only five objects
of this class type should ever be initialized.
After five, it should just fail.
And so-- then when they tried to initialize, if it's after five,
presumably this super init is going to fail
and self will be nil and then will just return self.
Yes? [Inaudible Remark] Yes.
Yes, yes. Self, this are two things you see in languages,
there is no this in Objective-C, they just call it self.
It means like-- it means this current object.
So, when I say-- when I have a Student,
like I just allocated the Student and then I passed
that Student the message initWithName, whatever,
then self refers to that Student I just passed the message to.
And so, similarly, self.age
which is also equivalent to self setAge, age.
So, self.age refers to this student.
We want to set our own age instance variable to age.
[ Inaudible Remark ]
Which do you need spell out?
Spell out.
[Inaudible Remark] This?
So, this gets into that-- there should always be--
and you can look up these exact words designated initializer.
So, not really going to go into deep detail here, but,
every class should have exactly one designated initializer.
And this is, in other languages, you might see it
as like you define one constructor,
that sort of all other constructors
that you have called.
And so here, we decide
that initWithName should be our designated initializer,
which means that init needs to call our designated initializer.
If we then defined a (id)initWithAge method,
that should be int, then this must also call our designated
initializer and we'll use the defaults above,
beyond andAge, age.
So, there should always be one initializer
which is your designated initializer.
And also, that designated initializer needs
to call the designated initializer
of your parent class.
So, notice that init
and initWithAge are not calling super init,
it's only our designated initializer
which is calling super init.
So that's just-- if you start to find your own initializer,
just make sure you follow this convention
and you can remember just googling designated initializer.
And also notice that I should not do this.
Why is it?
I should not do this because this is not appropriately
setting self.
So, we want to set self to whatever that happens
to return and then return self.
[ Pause ]
Questions?
And then going back to main.
Now, we see that all in one line we're allocating a student,
initializing it with a name Alice and the age 20.
>> So the things we're allowing is super--
>> In here?
>> Yeah.
>> So, imagine we are-- go back to the example from a while ago
where were have like NSObject and we have person,
then we have student, then we've 8th grader.
So, I want to define a new initialization method
for 8th grader and I decide that to initialize it like say,
it has an instant 8th graders.
Let say kindergardener.
So, kindergardener has an instance variable favorite color
and so we decided that like the default initialize--
the default value for that instance variable should
be blue.
So, we define an initializer that says,
"That should be blue" except if we don't then call super init,
super now refers to, if we are a kindergarderner,
super refers to student.
And so if we don't call super init then we're not initializing
all these instance variables that happened to come
from the student class, in the person class,
in the NSObjects class.
So, you should always initialize your superclass.
Similar to like you should always initialize any object
that you allocate, you should always initialize your
superclass and these two methods happen
to initialize the superclass
by calling the designated initializer
which initializes the superclass.
But again, this pattern like this is the pattern
for writing your own initializer.
So, we should almost always copy and paste this and then
like in these curly braces is
where you set your instance variables
or NSLog whenever it is you want an NSLog.
[ Inaudible Remark ]
>> Yeah.
[ Pause ]
'Cause there might be something in that superclass that is
like essential for everything else to work.
[ Pause ]
Any other questions?
[ Inaudible Remark ]
>> Why does init with age not needed?
Because it's calling init with name and age.
It's calling this method which itself call super init, OK.
[ Pause ]
OK. We'll take the five minute break.
OK. So, am I-- am I now louder?
So, now, talk about collections for just a second.
The only ones we're going to see right now are these NSArray
and NSMutableArray where NSArray is in MutableArray
which pretty much means like one set exists.
It is what it is.
You can't change it.
MutableArray is going to be useful and that we're going
to be able to just keep adding things to it.
NSDictionary and NSMutableDictionary,
so those are going to be useful
for like KeyValuePair type stuff, associative arrays, maps,
whatever, hash tables, whatever you want to call them,
that's what you're going to use those for.
Set is just another example of the collection.
NSArray is going to be the most commonly used
and we're going to use it right here.
So, looking at the next example.
[ Pause ]
OK. So, Student.h and Student.m haven't changed.
It's main.m. Now, we're trying to do something interesting
where we have a NSMutableArray of students
and we're just allocate-- allocating it and initting it.
And then we want to insert into that array Alice and Bob.
So we've done it in one line.
If we wanted, we can do the same thing.
We can do--
[ Pause ]
So, the NSMutableArray class defines an instance method
called AddObject that is just going
to take some argument with type ID.
And so since student star is an object type,
that isn't appropriate ID.
And then we're going to do that again with Bob.
So you name this as an array where the first element is Alice
and the second element is Bob.
And then here is I referenced this a while ago
that we have this for in syntax that we're able
to use with collections.
So this well also wok for dictionaries and sets.
So for each student in this NSMutableArray we want
to greet that student.
So one thing that's somewhat important to remember is
that everything inside of this array is just stored as an ID,
like there is nothing enforcing
that I only put students into this array.
If I wanted, I can put a student and then NSString
and then another student
and then some UITableViewController that's
it's up to you to enforce that everything is of the same type
or if you don't want to enforce
that you then just make sure it's makes sense.
You know what you're doing, but like if I wanted I could say,
this and this isn't going to work
because NSString doesn't have a name and age instance variable,
but it doesn't know what's inside of the students array.
So for all the compiler knows, it is an NSString.
This is where it can be somewhat dangerous dealing with ID
and this is also why you might need to be dealing with casts.
So, you might want some cast these return values
to the appropriate things.
Okay. So, questions on this iterating over an array?
Yeah.
[ Inaudible Remark ]
So it's-- how it's working underneath the hood is
that this NSMutableArray class needs
to define how to iterate over it.
And so in this method that it's defining for how to iterate
over it, it's saying that like,
"I'm going to do it in this order."
So it's saying that like index 0 is the first thing
that should be return then index 1 then index 2.
>> Is there any way for that to [inaudible] like-
>> So, we'll see-- I don't think there is to-- directly to erase.
We'll see though that protocols at the very least are ways
to make IDs a little stronger.
There are ways to make sure that these IDs are at least objects
that conform to a specific interface.
I don't think there's any generic type construct
in the language.
[ Pause ]
Okay.
[ Pause ]
Okay. So that's the syntax we just saw
and notice here we are saying for ID foo in bar
and so we don't know what is inside a bar
and so all we can really say is ID unless you happen
to know what it really is.
[ Pause ]
Okay. So, categories is a--
actually, let's ignore that for a second
and let's do another example first.
[ Pause ]
Student 8.
[ Pause ]
Okay. So the point in this example is I've decided I don't
want to print these things in just whatever order I happen
to insert them into the array.
I first want to sort the array and then I want
to print out the sorted array.
So, there are couple of ways we can do that.
I inserted them in the order, RJ, Chris, Rob, David, and so,
here by looking
at the NSMutableArray documentation I see
that it has a whole bunch of different ways
of actually sorting things.
One way is this sorted array using selector method.
First, let's look at Student.h and Student.m. So,
inside of Student.h,
I have defined a new method called compare.
It's returning this NSComparisonResult,
and the only reason that's relevant is
because this sorted array using selector method expects a method
to be passed to it that returns an NSComparator result,
whatever it is.
So, this compare method is going to take another student
and just compare ourself,
our current student with that student.
Looking at the implementation of that,
I decided that I'm just going to compare it by name.
So, I'm going to use self.name references the NSString
that is my name and then I'm going to compare
that like the NSString compare method, I'm going to use
that to compare to the other students name.
And because this compare method returns an NSComparisonResults
that is an easy way of making sure
that I return an NSComparisonResult.
OK. So, now that I defined this method for students,
I'm now going to say here that I'm going
to sort the student's array using the selector compare.
So this special syntax @selector, remember that methods
and selectors are kind of like interchangeable words almost.
So, I can't just say like this 'cause that's not really a
valid syntax.
I want to say that I want to use the method compare colon,
and so to actually specify the method compare colon,
I wrap it in this special selector keyboard.
And so, what this sorted array using selector method is going
to do is iterate over the student's array calling the
compare method of each student to say like, OK, student 0
and student 1, how do you compare to each other?
And then like depending on how they compare is going
to determine whether student 0 belongs in front
of or after student 1.
So compare has to exist for everything
in this student's array.
And then let's just run it
to make sure that's the case that this works.
So we see a print Chris, David, RJ, Rob which is what we wanted.
[ Inaudible Remark ]
>> So how do you in here--
and you can also decide that we just want to compare ages.
This isn't quite right because they're ints and I'm not sure
of what NSComparison looks like.
It might just be like return Self.age less
than other Student.age, or I guess maybe
like if 1 is less than, I'm supposed to return 1.
Or if they're equal, I return 0 or else negative 1.
I'm not sure what NSComparison, what it was supposed
to look like actually.
So, another-- let's go to here again.
So, a useful syntax that we've already seen this useful
shorthand for defining an NSString, that's blah, blah,
blah with the @ sign in front of double quotes.
Another useful syntax is an @ sign in front of brackets
for shorthand for defining arrays, so and NSArrays.
So now I've defined an array, an NS array with two objects,
Hello and World, two NSStrings.
And additional shorthand that's somewhat is @
in front of any number.
So this defines the approach like NSString was the first one,
NSArray was the second one.
This defines an NSNumber with the value 42.
And so, what may or may not work.
What I'm going to show it right here.
No, actually that won't work at all.
So, I might be able to do init NSNumber alloc.
I just want to save the sense of working at this point,
init with int self.age.
And then I want to compare that, now I have a compare method.
Compare to another NSNumber should be NSNumber alloc init
with int, other student, age.
[ Pause ]
OK. So questions on what I just did there.
Yes.
>> You didn't use the selector up here.
>> So, I'm not using-- here,
I'm just defining the compare method.
It's when I want to actually reference the compare method
that in here I say the method I want to use is compare calling.
And this is again like I said before, like the literal name
of the thing includes the colon.
So here I'm referencing the method compare colon
and the definition of it, I don't need to use @selector.
[ Inaudible Remark ]
A method to a method, yeah.
'Cause if it were a function,
I wouldn't need to use that selector.
I could literally just use a function pointer
but you don't need to deal with those here.
There is some-- there is probably some spacing
error here.
All right, 'cause I don't need this, whatever.
That's the general idea.
So, that's that.
Questions before I move on to a similar idea?
Yeah.
[ Inaudible Question ]
>> And just as-- remember, it's like C where--
it's like C where this, in order to get the prototype
for this thing, I can literally just like copy this, paste it,
put a semicolon at the end.
So the prototype is just the first line
of your definition of the function.
OK. So, that's that and now we're going
to students 9 'cause we're getting into categories
which that's not very helpful so here, let's-- OK.
So, the idea behind categories is notice that in order
to do what I just did, I needed
to actively modify the student class which is fine
because I'm the one who created the student class so it's fine
for me to go into the student class and add a compare method.
But, what if this class that I need
to modify is not something I have access to?
What if it's in some compiled library or it's one of the--
one of the foundation classes or an iOS class.
I need to add a method to it
but I don't have access to the source code.
So these are what categories are
for therefore extending existing classes.
And so, in Xcode you can actually do this like file new,
file and then Category and then
like walkthrough through the steps.
And the default format of these categories, so remember,
I'm working under the assumption
that I don't have access to the student class.
So the default format of these filenames are student
which is the class that I'm extending, plus,
and what I happen to call the category.
So here, I am extending the student class
with the category StudentCompare and this is just the syntax
that you're free to look out whenever you happen to need
to extend a class like this.
So, this extension of the student class is going
to include this method.
A category is not able to define instance variables,
it's only able to define new methods for a class.
So, looking at the implementation of this category,
again, it's-- the category itself is StudentCompare
and I am extending student
and I'm implementing it basically how I implemented it
before, exactly the same, except I'm able to do this
without ever touching the original Student.h
and Student.m. And this will work exactly the same.
Now, in main.m, inside of importing Student.h,
I import Student+StudentCompare.h. The
StudentCompare.h is what is importing Student.h.
And everything else in here is the same.
Yes.
[ Inaudible Remark ]
>> Oh name, OK.
[ Inaudible Remark ]
>> Oh these angled brackets and quotes.
So the angled brackets refer to like these special directories
in the file system, in the operating system that it knows
to look in to find these files.
So like Foundation/Foundation.h is in one
such special directory.
Whereas these double quotes are what you're going to want to use
to refer to files in your current project.
So, in this project, I have a Student+StudentCompare.h file.
Double quotes is like relative
to my current location whereas angled brackets automatically
goes to these special directories.
Yeah?
[ Inaudible Remark ]
You mean by addendum, do you mean like this sort
of stuff, this category stuff?
[Inaudible Remark ]
Oh, then yes.
So, in student Compare.h, well,
let's say Student.h was a foundation class.
>> Yeah, yeah.
>> Then I would do foundation/Student.h.
And inside its main, I would still do the
Student+StudentCompare.h. I wouldn't import the original
foundation version of things.
I would import my version of things
that have been overwritten.
[ Inaudible Remark ]
Yes, it's actually just an extension.
It's the-- it is the same class.
And anywhere else in your code that uses
that class could also use that new method.
If it doesn't happen to hush import,
the correct category file, the compiler will complain
that like it doesn't know that method exists.
But that method now actually exists for that class.
[ Pause ]
[ Inaudible Remark ]
>> Mm-hmm.
>> Where is NSComparisonResult coming from, is that a library?
>> So, that's something in Foundation/Foundation.h,
we could actually just look it up, NSComparisonResult.
So, something about the Apple documentation is
that it can be overwhelming.
But it has a lot of good examples so feel free
to ask questions on like the message board if it--
you just find yourself lost in a path
of various methods and stuff.
So, data types, what was I was looking, NSComparison.
So, it looks like NSComparisonResult is--
all right, this syntax, you don't even know yet.
Let's hold on for that.
That's going to be the next thing.
But NSComparisonResult is just something
that foundation defines.
And that's why I wasn't 100 percent sure what it is.
I just know that the compare methods of NSString
and NSNumber also a different return NSComparisonResults
and so that's what I use.
But if you wanted, you can construct your own
NSComparisonResult to return.
OK. Questions for the next thing?
So, next thing is this.
Again, I think slide is going to be worthless.
So blocks, so that's the general format of blocks,
but that's worthless so--
looking at the example of using a block.
[ Pause ]
OK. So, back to Student.h and Student.m,
I have not modified them to include the compare method.
I have not added a category to extend the class.
Instead, I've used what's called a block.
So a block is kind of like an anonymous function
in other languages.
It's-- it doesn't even have to be anonymous.
If you wanted, you could assign it to a variable.
It's kind of like, if you're familiar with the term,
it's like giving objective-C first class functions to like
in objective-C, I'm not really able to just define a function
in the middle of this method.
That's not entirely valid, whereas,
I am able to define a block.
So, just like in JavaScript, you saw a syntax like this.
Here, we have-- we are using a different method.
So, before, we use sorted array using selector.
Now, we're doing sorted array using comparator.
And so, this comparator expects a block
that this little caret symbol specifies
that what is following this is a block.
And this is the return type of the block, NSComparisonResult.
This is the two-- now this is the type of the first argument
and this is the type of second argument.
And I know this because if I look at the documentation
for sorted array using comparator,
its argument is supposed to be a block
that returns an NSComparisonResult
and takes two arguments that are both IDs.
So this, I got directly from the documentation.
And then I need to define the function itself
so I have my little curly brace.
And in here, I'm doing the same sort of thing I did before.
We see here that I cast A to student star and that's
because in here, A is just an ID, in here, B is just an ID.
So if I actually want it to be a student object, I first need
to cast it before or passing it a name.
So Student star A name, Student star B name,
gives me these two names
and then I use the NSString's compare method.
So I don't have to construct my own NSComparisonResult.
And we know that this appropriately returns an
NSComparisonResult like this at it should.
So blocks anonymous functions.
The syntax is a little strange but it's convenient
that like I don't need to define a method
in the student class just to sort this array,
which like that was a very heavy-handed result just
to get a sorted array.
[Inaudible Remark] Yes.
So that's where-- I don't remember the syntax.
But it's going to look something like-- so--
[ Pause ]
It's something like what it returns,
then in parentheses what I want to call it, then ID, ID equals.
And then pass it--
[ Pause ]
-- to here.
Didn't complain.
[laughs] So, if you're familiar with function pointers in C,
I just sort of used that same syntax.
I replaced the star with a caret.
So, here is, we are defining a variable called func
that is a block as indicated by this caret.
This is-- the return type
of that block is NSComparisonResult.
The arguments are two IDs.
And you're assigning that to this block.
And then we're passing that variable
to that function, to that method.
[ Pause ]
Questions?
[ Pause ]
OK.
[ Pause ]
So couple last things.
[ Pause ]
OK, so protocols.
We're not going to go into deep detail today about them.
But they are going to be pretty substantial in your iOS usage.
So the syntax for this, remember that well, in our interface,
we would also say like :NSObject.
But here, this angle bracket syntax is how we're going
to specify that it must adhere to some protocol.
And so the NSCopying Protocol,
this is where I'm saying the protocol is kind of interfaces
from other languages by saying
that the student interface implements the
NSCopying Protocol.
I'm saying that it must implement the methods
that NSCopying says, anything
that implements me must implement.
So, looking at the implementation now,
if we look at NSCopying, it says that you must implement a copy
with zone function method.
And so here's us implementing it.
You don't really have to care about the syntax of it for now
or the-- what it actually is doing.
Just the idea that since student implements the NSCopying
Protocol, it must implement all the function,
all the methods that NSCopying says.
And the use of this as we see is going to be like a lot
of these functions that--
or a lot of like classes that you're going to be using
with iOS, like a lot of these drawing classes,
are going to expect you to pass it objects
that must adhere to certain protocols.
For example, UITableView is one.
Let's actually looked at documentation,
this documentation work.
[ Pause ]
OK. So we see in the documentation
that it looks like a data source.
So, UITableView is, in like your iPhone,
it would be like your contact list sort of,
it's just like a bunch of rows with data in them
and you can scroll up and down on it.
So here, UITableView defines a data source property
where the type of that data source is just an ID
that implements UITableView data source.
And so this is important because if you then set this property
to be some object, that means
that that object must implement this protocol,
what this protocol says must be implemented are--
so some methods are optional, some are required,
so these two methods are required.
And so, when you set that property of a UITableView
with some object, that object must have these two methods.
Let's say, like how many rows there should be in this table,
in this section, and also what should go
in each particular cell.
So when you try to create a TableView,
you need to pass some object that is capable
of populating the cells of that TableView.
And so, UITableView knows that you are capable of doing
that if you implement the protocol.
And you'll see that that sort of pattern is going
to be pretty common with a lot of things you do.
Questions with protocols?
[ Pause ]
And that's really why I like it.
You compare to like a Java interface.
Protocols are much more similar to those
since like protocols almost define a new type kind of,
whereas like an interface in Objective-C is just a list
of all the methods that you implement.
It doesn't say anything intelligent
about like, "OK, you're welcome."
Really, what protocols allow are like multiple objects to all--
multiple classes to all fulfill some common purpose.
So as long as like-- an example are all these
like enumeration classes, the collection classes, NSArray,
and NSDictionary, and all those,
as long as you appropriately implement some protocol,
then you are able to use the fast enumeration syntax
on that object, that for...in syntax.
And, again, much more than that.
All right.
Just-- so you've seen it.
NSExceptions is very similar to some other languages, the try
and catch blocks and we also happen to have finally.
So that's just to know it exists.
You probably won't even use them that much,
but that's useful to know.
NSError is somewhat of an alternative.
So, instead of having to use
like the try-catch-finally syntax can be somewhat large,
especially if like each one of those do something here,
just like a single line then you've sort of like wrapped it
with three times as many lines are accomplishing something.
So, NS-- or well, this sort of syntax,
this is one of the rare scenarios
where are you are going to be using ampersand still, so--
again, we're never dereferencing an object,
but we are passing the address of an object.
We are passing the address of this NSError so that
if something happens to go wrong when we pass the method bar--
the method is called bar:error:.
So when we pass the method bar:error: foo,
if something happens to go wrong,
then foo will instantiate an NSError object and set E
to be that NSError object.
So, inside of here, if something went wrong, E will not be nil.
If we just pass E, then inside of this function, this method,
it would have to dereference E
which is something you shouldn't be doing.
You should never dereference an object.
Plus, if you try to dereference E, you'd be dereferencing nil.
[ Inaudible Remark ]
So it will-- by returning nil, it's indicating
that something went wrong and then inside of here, now,
since something must have gone wrong, E must be set
to something that isn't nil.
Inside of the function, it must have instantiated an NSError
object and did like star-- star E equals this NSError object.
[ Inaudible Remark ]
Well, it's-- well, the function
or the method is bar error, bar:error:.
But if something goes wrong, yeah.
It-- that's just like when you read the documentation,
it will say like, "If something goes wrong, nil will be returned
and error will be set to some NSError."
So, it's also possible that it will return void and then it's
up to you just to see if E is still nil
and that's the way you know there was an error.
But, that's just-- in this example, we say, nil is returned
on error and what that error was is inside
of E. [Inaudible Remark] Yeah, it's not.
So, instead of just failing, we just put it inside of E.
But other things do use the try-catch syntax
so some things don't have this.
All right.
Any other questions?
[ Pause ]
I think that's it for our Objective-C intro.
If there is anything left, it was a lot,
but we haven't really done any iOS stuff so we'll throw all
that at you next week.