iPhone • 1:00:51
Objective-C is the language of choice for development on both Mac OS X and iPhone OS. Understanding Objective-C basics is key to creating great applications. Learn about its syntax, common classes, design patterns, memory model, and runtime engine. If you're new to Objective-C or just need a good refresher, this session is for you.
Speaker: Mike Jurewitz
Unlisted on Apple Developer site
Transcript
This transcript has potential transcription errors. We are working on an improved version.
So I’m Michael Jurewitz, I’m Apple’s Developer Tools evangelist and well today we’re here to talk to you all about Objective-C. So let’s go ahead and let’s dive in here. So what are you going to get out of this session? Let’s focus on that first. Our goal for this session is to give you a working understanding of Objective-C. When you leave here, I want you to be able to open up the various example projects that we have, better understand them and also understand a lot of the common classes and design patterns that you’re going to be using on both Mac and iPhone.
So we’re going to move pretty quick and we’re going to stay you know pretty broad in terms of our coverage but hopefully we should give you a good foundation to be able to tackle the rest of the week. Alright so as you already know we’re here to talk about Objective-C. This is the lingua franca on both the Mac OS X and the iPhone. This is the language that underpins really the powerful framework that you’re going to be using for development on either operating system.
And Objective-C is not a newcomer on the stage. Objective-C as a language has actually been around since 1984 and has been through a rather long history, whether you want to start off with its creation to its first usage, really commercial usage with NeXT to where they came over with NeXT when Apple acquired them and really you’ve got 25 years of evolution of this language.
And so for all that time the designers of this language have really been working and iterating and trying to solve these common object oriented design problems that you’re going to run into so I think you’ll find it’s actually an extremely versatile and a very powerful language to work with.
And in fact a lot of languages that came later, especially things like Java, as we go through some of these things you’ll notice some similarities and in fact we actually had a lot of the same things first and Java in many ways took a lot of hints from things that you’ll see in Objective-C. So what is Objective-C when you get down to it? So Objective-C is a superset of C. Anything you can do in C, you can do in Objective-C. This also means that you’re going to have the same data types available to you.
You’re going to have the same basic mode of operation. Now where Objective-C really differs though is that Objective-C is a dynamic language, which is actually a stark contrast to what you’re usually used to in something like C or C++. So we actually have dynamic method dispatch or the ability basically to have an active run time that’s playing a part in the messaging of objects and making sure that things go where they’re supposed to and participating in this chain.
This facilitates the ability to have runtime decision making so that your class can actually adapt what it does to your application and the frameworks that it’s using can adapt on the fly to the situation. And you also have the ability to extend your classes at runtime. This is really powerful and we’ll focus on some of this in a bit.
So let’s take a look at a very simple comparative example just to start with the most basic thing which is actually you know calling a method in 2 different languages you might be familiar with and we’ll take a look at it in Objective-C. So in C++ if you’ve got some pointer to an object and you want it to go do something, it would look something like this. You’ve got your arrow operator. You’re going through your usual stuff.
In Java you’d be using your dot operator for this. So what does the same message look like in Objective-C? You’ve got a square bracket, some Object which is the message, the actual instance you want to send this message to, a space and then the actual message itself, in this case, doSomething, followed by another square bracket.
So let’s take a look at a couple more examples here. So pretty similar we’ve got anEmployee, this is the instance we’re sending the message to. Then we’ve got the method that we’re actually sending, in this case this is salary. We would presume that this probably is going to, you know, return with the actual salary for this employee and we can assign that to a variable etc. For a single argument, what does that look like?
Well you’ve got your same instance and now you have your method which is setRaise: And after that we have the argument that we’re passing in. So anytime you’re going to be dealing with arguments in Objective-C, your method is going to have a colon and it’s going to be followed by the actual argument that you’re passing in. But what if you’ve got more than one method, what’ll things look like when you start dealing with that situation?
Well you get messages that look like this. So you still have anEmployee which is the instance you’re working but now the method has actually been broken up and you see our method here is setWork:withDeadline: but we actually have the arguments interspersed with the method name itself and you’ll notice it always come with setWork: then it’s argument, a space, the rest of the method name, so withDeadline: and then today.
So this is really important because this makes the language extremely readable. If you were to approach that method for the first time and say well what parameters do I expect to be passing in here, you could probably take a guess just trying to, you know, throw a dart really quick and figure things out.
The difference really here is readability. Let’s say we were trying to create some new glass objects, this might be how you declare something basically in C++ or Java right so you know new Glass and it takes 3 arguments and you know 5, 10, and 0.75, sure, you know, whatever. But you know you might be surprised say 6 months from now when you go back and actually look at the header and realize what that third parameter really was.
[laughter] It makes it a little more clear when you’re working with Objective-C, a little more wordy but again what you add in terms of verboseness you gain in terms of clarity. So let’s talk about working with variables here. We’ve sent some messages but obviously what we want to do something with those return results.
So if you want to declare an object it’s just like in C or C++, you’re going to be using a pointer. So we had an employee object and we wanted to begin working with it we’d probably end up declaring a pointer to an employee. Now if we wanted to create an employee then say we had an employee class. Maybe that class had some method called new employee and this is a key point in Objective-C is that a lot of times classes have convenience constructors.
Basically the idea that you can send a message to this class and it’s going to go ahead and turn around and create a new instance for you, set it up with some initial state and hand it back and say here you go. You can begin working with this. In this case this is just new employees that we’re doing.
But just as commonly you’re probably going to end up actually allocating and initializing the object yourself and so you might end up sending the employee class the message alloc and then follow that with init. So what’s actually going on in that particular message send that deserves at least taking a little more detail here?
So when you allocate an object the first thing you’re doing is basically causing that object to you know allocate the memory that you’re going to be working with. And you’re always going to have all of the instance variables that you’re working with in this object initially set to nil. This is basically zero in Objective-C. You’ll see nil quite a bit.
Now once you’ve allocated that memory, you need to give the class an opportunity to set up initial state, right? So that’s where the init method comes in. This is where classes are going to be doing that kind of work. So we send the init method and as we can see here this class happens to set up a default value for name which is just the string name. Now often classes also have convenience Initializers that you can use. So they might actually take arguments that you can pass in so they’ll return back to you an object that already has some additional state set up for you.
So in this case if I said [Employee alloc] initWithName: and I happen to pass in bbum as the name in this case, we’d get back an object with this state already set up for us. So now all these messages that you’ve seen are all represented in Objective-C by a based type called a selector.
This is a first class data type in Objective-C and it’s actually an incredibly powerful concept because it serves as the basis for a lot of the design patterns you’ll see throughout Cocoa. So things like Delegation, Target/Action, working with NSThread, we’ll talk some more about these in a moment. But what is a selector, fundamentally?
So in the examples we gave you for salary if you’re writing code and you wanted the selector you’d say @selector(salary). And this would return back a variable type SEL, selector, that you could work with in your code. And there’s actually API that works directly with these. Similarly with setRaise: you’d get the selector back in this fashion and the same thing with setWork:withDeadline: As you’re noticing methods that take arguments, the colons are very important. Make sure that you include those when you’re doing things like annotating a selector here.
Now this is particularly powerful because like I said these selectors, it’s all in the name, all in how you use them. And so while you might not find yourself using this method all too often, we actually as framework developers use it quite a bit to dynamically determine what your classes may have implemented. So you actually have the ability as you’re running through your application to ask an object, hey do you respond to this selector? You implemented this method. Is this something that I could go ahead and call on you if I wanted to?
So you already have this sort of, the very beginnings of some powerful introspection building up here. Ok so we’ll come back to selectors in a little bit but let’s go ahead and let’s move on to some of the frameworks because it’s enough to talk about language and messaging but you really need to have, you really need to understand sort of what are the core classes that you’re going to be working with in a language.
So frameworks on Mac OS X or iPhone are basically synonymous with libraries, you might be familiar with packages, etc. But basically the two that we’re going to focus or the one that we’re going to focus on is foundation. Now you also hear about AppKit on Mac OS X and you’ll hear about UIKit on iPhone.
Let’s go ahead and let’s take a look at foundation specifically. So foundation is where you see the declaration for the core classes, the core data classes that you’ll be working with in Objective-C so the core elements and how you work with your application. So obviously we’ve got a string class. It happens to be called NSString. As we go throughout all this API and you see API that begins with NS you might ask yourself, what’s that all about?
So that stands for next step. That’s a little bit of history from where the frameworks have originated in the first place. So if you wanted to declare just a constant string here would could just say NSString *myString and we use a@ sign with quotes to actually use that string in our source code.
Similarly NSString has a convenience method for just returning us back a string that’s already used a print F style format substitute in the values so that string right there would say WWDC2009. And NSString also has a lot of convenience methods for working with paths themselves so for instance if you had a path string that was a path say to some cash file then you can actually ask that through some methods on NSString to break it up into various path components, say into an Array.
And then you might ask what the file name was based on that last path component so in that case it would return datacash.txt. And finally NSString also has some very powerful facilities just for reading files in the first place. You don’t have to go through any loops in terms of trying to open the file yourself, reading it character by character or some you know amount of characters. You can just ask NSString to go ahead and just say, go open that file for me please.
I want to be able to work with this, this string object. Alright we’ve got Arrays. Arrays come in both Mutable and Immutable variants, in fact so do Strings. So you have NSString and NSMutableString. So your Mutable variants are basically ones that you can manipulate. You can change their values, you can add things to them, you can subtract things from them. The Immutable ones, once you create them they are set in stone. And these are basically ways in which you can work with these things and there’s different performance tradeoffs here for the various ones. But getting back in Mutable Array is very simple.
You just say [NSMutableArray array] and you get back one that you can begin working with and you can start adding objects to it. For Immutable Arrays you’d want to of course create them with their content at creation time otherwise you’d have an empty Array. And you can do things say like taking those Array values and then using some NSString methods to say join them by a common string.
So you have “foo-bar-moof” in this case. Now an important point here as you’re working with, well actually here we’ll go on to the Dictionaries really quickly here. Dictionaries are also very similar. Getting a Mutable dictionary back is very easy. You can simply ask for a dictionary and once you’ve got that back it’s as simple as saying setObject for this key and you’ll forevermore be able to look up that object basically by saying you know what’s the value for this key?
It will hand you back the object. Now the key point is that as you’re looking at these Arrays and these Dictionaries is that if you come from other languages like C++ or Java you’re probably used to having to specifically type your Arrays, your dictionaries or your hashes, depending on where you’ve come from.
And one of the most powerful parts of working with these data types in Objective-C is that you can mix in just basically a heterogeneous set of classes, as long as they’re all objects that you’re passing in here, it doesn’t matter if you’re adding you know a string or an employee or a person into this Array.
It will handle it on the fly and it does so in a very, very performic manner. So creating Immutable Dictionaries again pretty easy, we’ve got a method called dictionaryWithObjectsAndKeys and we simply alternate between the value and the key and the value and the key as you go on.
And that’s terminated with a nil simply to let the API know that hey I’m done specifying things I’d like to pack in here. There’s also a class where you limit the Filesystem called NSFileManager. In this case this actually uses a design pattern that’s a singleton pattern so you ask the NSFileManager the class for the defaultManager. It returns one to you and you can begin working with it.
And the singleton pattern really is just to make sure that there’s sort of a common funnel point in terms of working with the file system. And you can do things like checking to see if a file is writeable at a path and then deciding if you want to you know create an object there. It’s your powerful way of being able to work with the file system at a higher level. And finally Foundation has really a lot of power for object introspection.
So in addition to just the two things I’ve listed here, as you’re moving along this dynamically at runtime you can ask things like you know, what kind of class are you? Or do you match this kind of class? You can ask an object like I showed you before, do you respond to this selector? And on the line of selectors you also have the ability to dynamically decide to go do something with a given selector. So you might be able to you know tell an object, hey go perform this selector, this go to work.
And your presumption is that that thing is going to do whatever that is. Now you might have some unit of work that you want to take and you want to execute say on a background thread and you’ve got some object you want to pass that’s some dataset perhaps.
We’ve even got methods for you to handle that kind of work. So performSelectorInBackground withObject where you simply pass in the selector that you want called on the object and the data that you want basically passed in as the argument to that method. And finally what would all of this be without the ability to log to the console.
So NSLog is how you print things out to the console. It takes just basically NSString, any kind of NSString will do. So you see just a simple debug statement looks something like that. You can do the usual print out style substitutions. So you’ve got over 130 sessions at WWDC and if you’re working with objects in Foundation, UIKit, AppKit etc., you can often print them out directly to the console using this %@ as the substitution in your string.
So for instance an Array you’ll naturally be able to print out what it looks like with console and so will Dictionaries and showing you what the key and the value actually are paired up as. And these work by sending a message to the Array and the Dictionary called description. This is a method that’s defined on NSObject and NSObject is the root class in Objective-C. And what this does by default is just print out an objects pointer value but it’s very common for objects to override this method to provide some additional detail for things like debugging.
So if it’s something that you want to provide for your own classes, it’s a good way to go. Alright so all this is good but let’s go ahead and let’s actually write a really quick demo here just to show you what it looks like to see some Objective-C and to work with it in action. So I’m going to go ahead and bring up XCode here and I’m going to use the welcome window to create a new project. And we’re going to make a Mac OS X application.
In this case we’re going to do a command line tool and we can choose the type of tool we want to create and we would like to do a Foundation tool. I’ll go ahead and hit choose here and we’re just going to call this Demo and save it on the desktop. And let’s make that a bit bigger, that’s pretty big. That unfortunately is not so big.
Let’s see what we can do about that, hold on 1 second. [silence] And sorry about that, oops, grab all those things and there we go. Ok should be a little more readable for you. Alright so this is a basic Foundation tool. You’ll notice that just like you might see for a C program, we enter here in at main, we’re still taking basically the argument count, the pointer the argument may have come in to the command line.
And then we drop down into some, basically into some more foundation Objective-C code. Now we’ll talk about this Autorelease Pool stuff here in a moment. You’ve already seen NSLog but let’s go ahead and I’m just going to delete this stuff out for the moment and let’s go ahead and start adding our code in particular. So what I’d like to do is just use the file manager to iterate through a directory and get us some files.
So let’s take a look at what we, let’s see here, alright we’re just going to use our home directory. That will work just fine. So we’ll use our NSFile Manager class and we’re going to declare a pointer to it here and just call this the file manager. And we’re simply going to ask NSFileManager for the default manager, again I showed you that in slides, this is just going to give us back basically the singleton for us to work with. And there’s an API for working with the file manager which is contentsofdirectory @path and that returns an NSArray of the actual items that are at that path. So let’s declare an NSArray here and we’ll call this Files.
And this is going to talk to the file manager and we’ve got contents, not quite almost, of directory at path, excellent. We got that auto completed for us. And I’m going to do /usersApple which is our user folder here, jump to our next argument. Now normally you’d pass in an error object here, if there’s an error get percolated back up to and you can check. We’re just doing a quick demo so I’m going to pass in nil.
And we’ve got this Array of stuff that we’d like to work with. Now we need to iterate through it. So Objective-C’s got a great construct for doing that. You’re probably familiar with something similar from other languages so we’re going to use our 4N Notation. So we’re going to say for, let me get that space back there, for files in files I’m going to go ahead and print out the actual name of the file here so we’ll say the file is named and we’re going to go ahead and type in file here because this actual, the element that it’s returning to us is an NSString with the file name but I don’t actually want to print out all the files because there’s a bunch of hidden files we’ll get back with that as well.
So what I want to do is basically check to see if the file starts with a period. This is sort of a common way of knowing that a file is hidden in the finder. So if the file has a period we don’t want to log so go ahead and just drop this on in here.
We’ll save that and we’ll go to the console here and I’m going to build and run. And we see right here, we’ve gone ahead and gone to our user director, grabbed all the files that are there, checked for the ones that are only don’t have a period in front of them and printed them all out.
So that’s pretty nice, pretty simple, pretty straightforward. Again you got a chance to see what it looks like, to actually work with the language in practice here, sending some messages, iterating through this collection. Ok so we’ve seen really briefly just how to write some really basic code. Talk about memory management here.
So now if you’re doing development for the Mac, you should be using Garbage Collection. Garbage Collection is both easier, faster and it’s going to help you be more productive with your code. Why is it easier? Well you don’t have to worry about managing the memory. That alone should be self evident.
Faster because we can actually better optimize for some things in Garbage Collection and really improve key points and key parts of your application that are going to depend on speed. And more productive, again you’re not having to worry about the memory management and especially as you’re getting started on Mac development this is going to help you out just to start writing code and not have to worry about these sorts of things. If you’re doing development for iPhone you’re going to be using Objective-C’s retain release model.
This is actually the original way that Objective-C has worked and it’s a simple system with a simple set of rules. So at the very basic level, Foundation tracks an object’s retaining references. You can think of this as basically as objects that care that this thing needs to stay alive.
And any time that you are creating or copying an object it most of the time means that you’re going to end up owning it in some respect. You’re going to be expressing some degree of interest in having that thing stay alive. So any time you use API where you say NSString new which is basically semantically equivalent to alloc init or you call anything involving alloc or any method involving copy, you’re going to get back essentially a retained reference from that message. So that object’s going to be sticking around basically waiting for you to say when you’re done with it. So when you no longer need one of those objects, you need to make sure that you send it the release message.
This basically balances out that interest you initially showed in it and makes sure that the object is going to get cleaned up by the system. So now if you’re working with an object say that somebody else has passed back to you and you want that object to live on say beyond the local scope you’re working with, maybe you want to stash it off into an instance variable and continue to have it for later. You need to make sure that you send it a retain message.
That’s going to add you as sort of one of the retaining references for that object to make sure that it sticks around. But this also means that when you’re no longer using it, when you’re done, you need to make sure that you send it the release message, just to balance that out.
So let’s say we created an Array with our NSArray alloc init. We’ve got back this Array that we’ll call foo. And maybe as we’re using this Array we might have, sorry we’ve got 1 retaining reference to that which is us, we’re the ones that created it. And at some point we might have taken that Array and you know given it out to somebody and they might have said, oh that’s interesting.
I need to hold on to that for a bit, to work with that for a while. And so they would presumably send it the retain message so now we’ve got 2 objects that have retaining references to foo. When that object is done it will of course send release to balance out its own interest in our Array so now we’re back down to 1 retaining reference.
And when we’re finally done using it we would also send release and we’d end up with no longer having any retaining references. And at this point is when Foundation will make sure that the dealloc message is sent to your object. This is basically your destructor in Objective-C. And the idea here is that this is going to be where you’re cleaning up state for your application, basically freeing it for your class where you’re going to be freeing up any memory that you might have allocated initially. So we’d send that to your object and the memory gets reclaimed by the system.
Now this is a simple system like I said and the rules are pretty basic here but there is sort of one corner case. It’s a little weird to deal with so I’ve told you that you wanted to be balanced about your usage of retain release but what happens say in the case with String where you want to send it that message, stringWithString and the idea is that you send this message to NSString, it gets it, it creates a new string for you and wants to hand it back to you. So how do you handle that situation, right, because NSString had to create the object so doesn’t it own it in the first place?
And if that’s the case then do you somehow have to let NSString know at the end when you’re done using it? Well thankfully not, which is why we have this concept called Autorelease Pools. And Autorelease Pools basically allow for an easy transfer of ownership of an object. They’re often used when, just in this case, you’re creating an object and wanting to vend it out to somebody else. You’re creating on their behalf. They’re the ones who are going to be using it.
They’re the ones who are going to have to take care of ownership of that object. And all you do in that case is just send the object the message Autorelease. And that will actually do nothing right at that moment but what it will do is make sure that at some point in the future that object has the message release sent to it, to make sure that it balances out the fact that you were the one that created it. So NSString for example in that stringWithString just turning around and saying NSString alloc initWithString autorelease. So it’s passing back an Autoreleased object to us. Now this has some consequences, this delayed release that you need to think about.
So if you’re calling that stringWithString, it means that you’re initially getting back an object with a single retaining reference because it was created but it had that Autorelease message sent to it, it’s an Autoreleased object so unless you retain it it’s not going to live basically -- unless you retain it you should expect that object is going to go away at some point. So this might be great if all you need is just a string to work with in your local scope. But if you’re expecting to take this string and then hold on to in an instance variable, that’s not going to be sufficient.
You need to make sure that you actually retain it. Ok so quick recap here, so if +alloc’d, +new’d, -copy’d or -retain’d, you must make sure that you later -release to balance that off. If you use the class convenience method and you plan on using that object beyond just the local scope, you need to make sure that you -retain that object, which of course means that you must later -release that object. Ok so with memory management more or less out of the way here, let’s focus on Class Design. So we’ve used some API, we understand what the deal is with memory management more or less, what does it look like to actually write a class in Objective-C?
So Objective-C, much like C or C++, is a header based language so you’re going to be declaring your interface for your class in your .h file. And you’re going to do your implementation for your class in an .m file. So let’s go ahead and let’s start off with our .h and take a look at what it looks like to implement a class.
In this class we’re creating a person class. So we start off this declaration with this @interface which is basically just the start of things. If you’re coming from a Java background, don’t get thrown off here. Just beginning our class declaration. The name of the class is next, in this case Person followed by a : and then the class that we’re sub classing, in this class NSObject is the base class in Objective-C. And you’ll notice here that we’ve only specified a single class. That’s because Objective-C is a single inheritance language.
So you’ve got single class inheritance. Now after that we’re got our instance variables for our class. In this case I want a string called name, an integer that’s going to be the age for the person and an Array represents say, their parents. Now below that we would have our methods for this Object.
So let’s take a look at these first 2 first. So you’ll notice we’ve got here, we’ve got personWithName and initWithName. They both take a single parameter. They’ve both taken NSString. Notice we’ve annotated that by having parentheses and the type that’s actually being passed in here and just the basic name for the variable. But if you’ve been carefully watching you’ll notice that one of them starts with a + and one of them starts with a -. So what’s that all about? So in Objective-C methods that begin with + are class methods.
It’s the idea that you intend to send this message to the class object itself only. So you would only ever use personWithName when you’re actually sending it to the Person class. The presumption here you would say + (Person *)personWithName: and you’d get back an object to begin immediately working with.
InitWithNames since it begins with a - sign intends for you to be working with an instance of that class so in this case you would have said person alloc and then initWithName. Now we’ve got some accessors for our basic variables here just for a couple of them so we have age and setAge.
You’ll see the return type for age is declared right after that - sign. So that first parenthesis right there is the return type for the method. So obviously age being our getter it’s going to be return (int) whereas our setter is not returning anything so it returns a void. Now these naming conventions here are particularly important.
You notice that we haven’t called this getAge for example. In Objective-C the way to do it is simply to name your accessor after the thing that you’re actually accessing, no get or anything else like that. That actually implies some different modes of access when you begin looking at other API’s.
So we just call it age and it’s very important that our setter is also called setAge. And as you begin working more and more with the frameworks there’s some very powerful facilities in the frameworks that will more or less depend on these sorts of naming conventions. And then finally we’ve got our parents accessor.
One returns a pointer to a Parents Array and the other one is just the basic setter for that Parents Array. Alright and finally we cap it off with a @end simply to say that we’re done declaring the interface for our class. So let’s go ahead, let’s hop over and let’s take a look at the implementation file here. So just like in your C baseline the first thing we’d want to do is make sure that we include that header file, which your notice this is #import and not #include.
So #import is what we use in Objective-C and it’s got a few additional smarts to make sure that you don’t have to worry about including the same header file multiple times. Anyone who’s been bitten by that in C or C++ knows what a pain that can be to deal with.
Finally you’ve got or next you’ve got your @implementation block. You simply say @implementation, a space and then the name of the class that you’re actually implementing. You stick all the methods you’re implementing in between and at the very end you tack on an @end and that simply says like that’s the end of my implementation right here. So let’s take a look at some of these methods, the first one being init. So init, like I said earlier, this is your basic initializer in Objective-C. If you’re coming from say C++ you’re used to your constructors for example.
This is basically an equivalent thing that you’re working with here. Now you’ll notice in this first line here in this method we’ve got 2 words here, self and super. So self is basically, you can think of this as self or as this, depending on what your background is.
It’s the actual object that you’re working with right now. Super is our super class so this is how you’re able to you know, send messages on up the change and make sure that they get handled by a super class if you want. So you might be asking yourself, what’s with this (self = [super init]), did he forget an equal sign there? So it turns out no I didn’t. This is actually what you’re going to find when you begin reading a lot of code on Objective-C and the idea here in this line is we’re asking our super class to go off and perform its initialization.
To basically set up whatever state that is deems fit. Now it’s possible that for whatever reason, maybe we you know passed in some bogus value to it, that it might decide not to return back an object to us and the error case is to return nil by convention. So what we do is by making sure that we assign back to self, back to ourselves, we’re basically checking to make sure that we just gotten back a valid object. So if you see that don’t be confused by it. It’s not missing an equal sign, I promise.
Now once we know that that’s gone and everything’s happened ok and it pretty much always does, then this is your opportunity to set up your own instance variables. So you’ll notice that I’m declaring my name as just the static String as a new person. And my parents Array I’m allocating initial storage words. I’m creating a mutable Array in this case because my class may intend to begin working with this on its internals and just assigning that to our parent’s variable.
And finally as a last step we make sure that we return ourselves. So the caller is expecting an object back from this call, we need to make sure that one goes to them. Now you’ll also notice that ID is the return type on this message. This is really important so ID is the basic Object type in Objective-C. So any object that you might be working with as you’re doing your development you can always know that you can refer to with type ID.
Now similarly if we’ve got an initializer we probably have to have some way to tear this all down or a destructor. In Objective-C, I mentioned earlier, that’s dealloc. And dealloc is not a place where you want to be doing things like freeing up file descriptors or cleaning up scarce resources.
This is purely for you to be cleaning up the memory that your class has allocated. So you’ll notice all we’re doing here is sending release to our name instance variable that we are holding on to, release to our parents Array we’re holding on to. We’re only holding on to an integer as the other variable. Now it will get cleaned up.
We don’t have to worry about that. And then we call super dealloc. In this case we’re just giving our super class a chance to clean up whatever its data has. So that’s pretty basic, pretty straightforward. Now if you’re working with a garbage collected system you’re going to have, you’re not going to have to implement dealloc.
And our Garbage Collective system does support finalization, in general you should avoid it, please, please avoid it. We actually have a talk later in the week that will go into a whole lot more depth on Garbage Collection and our run time team’s going to be available throughout the week in the lab if you have more questions on GC itself. So what does it look like to actually get and set a scalar type?
Well it’s actually pretty straightforward. As we implement these accessors here we’ve got age which is just returning age and we’ve got setAge which just takes a new one and assigns it right into the instance variable that we have called Age, pretty straightforward. When you’re getting and setting an object though it’s a little bit more involved, at least for the setter. The getter remains pretty basic. If you’re just handing back the object it’s pretty straightforward.
In the case of doing setName though there’s a little bit more going on. So let’s talk about that. So we’ve got newName being passed in here and the first thing we’re doing is checking to see if newName is not equal to our instance variable that we already have here called name. And all this is doing is just doing a quick short circuit to say are these pointing to the same objects because if they are we probably shouldn’t do any work.
Obviously somebody has gotten confused and set the same object twice. So assuming they are in fact different pointers we go ahead and we continue with what’s going on here in which case we now know we’ve got a new value coming in. So we want to make sure that we retain this new value as it comes in and our name instance variable of course is just a pointer to some other object that we have previously retained when it was set and so we need to make sure we send it the release message to make sure we balance out our interest in it from a memory standpoint.
And finally we’re going to have this pointer to a new name and we just say hey instance variable, here’s the new thing that you should be pointing at. Please use that instead. Now this is a, you know a decent amount but it turns out at least if you’re doing Garbage Collective code, this is nice and straightforward. You don’t have to worry about the retain release you can just say name = newName and carry on with your life.
[laughter] Enjoy that for a moment, it’s nice. Okay so if you’ve already seen as we’re working with these getters and setters though you’ve got a whole bunch of you know age, setAge, parents, setParents, name, setName. You’re doing this over and over and over again. And you know we looked at this problem in particular and say there’s got to be a simpler way for us to do this.
A way for us to encapsulate all the information that you want but lets you very easily express this pattern and that’s exactly what properties are meant to do. They really are this encapsulation of the setter getter pattern made easy. So properties lets you specify the storage semantics for your objects. So do you want the object copied when it comes in? Do you just want it assigned directly?
Do you want the object to be retained and have the old object released when a new one comes in, etc. So they encapsulate all of this. And they are also easy for you to override in case as we provide these things for you, you want to provide your own custom behavior for say one of the setters or getters.
So let’s take a look at some of the syntax here. So the first things are your property declaration will live in your header file usually down by where you would declare your methods. And it looks like the syntax @property you’ve got parenthesis with a comma separated list of qualifiers you might want to put in there and you’ve got the type of the variable followed by the name of the variable.
So in this case let’s talk about the first thing you can control which is mutability. Do you want a getter and a setter or do you just want a getter? So basically read only versus readwrite. In this case we’ve got @property(readwrite) float speed. So this is going to generate a speed and setSpeed for us for this float attribute.
For memory management, like I said before you can control whether you want to assign, retain or copy this value. So you say @property(copy) NSArray *passengers and now we passed in a new value that’s going to get copied for us into our own unique object we can begin working with. Often a very good idea when you’re working with say Strings for example, when you want to make sure you’re the only person that’s owning the string from now on.
Now another one that’s very interesting is nonatomic and if you’ve done of any bit of UIKit programming, you’ve just like touched that surface, you’ve probably seen this quite a bit in the property declarations in UIKit. So properties by default offer atomicity both in getting and setting their values.
And this protection for when you’re working with multi-threaded situations comes with a little bit of a cost under retain and release. And so it might be the case if you’re working with code that doesn’t expect to having to deal with multiple threads that you don’t want to necessarily pay this performance penalty. And specifying nonatomic is what will do that for you.
So in this case we’re taking our NSArray with our passengers and saying nonatomic retain, in this case retain the new one when it comes in but make sure you do it nonatomically. Now the good news is that if you design a class like this and later you decide that you want to go back and you want to actually have these accessors be protected with this atomicity all you have to do is remove that nonatomic keyword, recompile and everything will get taken care of for you.
And finally you have the ability to actually determine what the name of the setter and the getter that are generated will be as part of the property. So Objective-C has a boolean type called a bool and it’s customary in Objective-C with the getter for boolean types to word them in the form of a question.
That makes it a little bit more expressive as you’re actually doing things like checking conditions. So if we had a bool called going fast we would name the getter isGoingFast so this how you can specify that in your property declaration. So let’s take a look at our actual class and see how we can benefit from Properties.
So the first thing here let’s take a look at our age and setAge. So we can take this and rewrite this as @property(readwrite) int age. Pretty straightforward, pretty simple but it turns out readwrite is actually the default for property so we can just remove that entirely and just say @property int age, same thing for our parents Array.
In this case we’re going to make sure that the object gets retained, that’s getting passed in so we say @property(retain) NSArray *parents. So we’ve gone from this to this, already a pretty nice savings. Now what’s more is if you’re doing 64 bit programming or iPhone programming, you can actually get rid of your instance variable declarations completely because properties will take care of actually providing storage for these attributes themselves. So if we were to convert our name attribute into a property as well, our class declaration would look something like this.
We’ve got one right down to these 3 lines. They’re very expressive. We know exactly what’s happening here. We’ve got a setter and a getter for our age, a setter and a getter for parents and we know the object we’re passing in is getting retained and a setter and getter for our name and we know that that value is getting copied. So this is a way for class designers, for yourselves, to basically produce your own API contracts for the world that you work with.
So people know and can anticipate what you are doing with these values at least as far as memory ownership is concerned. Now once you’ve actually declared these properties you go off to your implementation file and most of the time you’re going to end up synthesizing these properties so what does this do for you? Well first of all basically all it does is tell the compiler, hey go look at my header file and whatever I said to do there, make sure it happens.
You know, insert my age and setAge, make sure that I’ve got storage allocated for me etc.. So all that code that I showed you where you wrote these setters and getters and everything, after you’ve typed that one line, that @synthesize, you can get rid of all of it. You don’t have to have it there.
It’s handled automatically for you by the compiler. But oftentimes you’re going to end up in a situation where you say you’ve got some setter and you really want to put in your own custom behavior there. You know, maybe you want to just log to the console when a new value comes in.
Maybe you want some you know side effect to happen as a result of some value being set. So it turns out if you want that to happen all you need to do is just implement the method. So if we wanted setName to have our own custom implementation we would do that just by in our implantation file actually implementing setName.
In this case we would like to make sure that a mutableCopy is made of the string. Basically we’ve passed NSString so it’s not something that we can change. We make a mutableCopy and now it’s an NSMutableString that we can actually fuss with and do whatever we want. And the nice part about this is that the compiler is just going to automatically notice that you’ve done this and it’s going to make sure that you use this implementation for this method.
Alright the next thing properties get you is Dot Syntax. So for example if we had a new person, this bbum person and we wanted to set the age for that person, we could just say bbum.age set = 35. And in this case this is actually sending an Objective-C message.
So if you’re from a Java background probably all this makes sense. But if you’re coming from a C++ background or C background it’s important to note that this is not structure based access. This is an Objective-C message that’s being sent here. So this is semantically equivalent to having written bbum setAge:35.
Similarly you could use property.notation for getting values. So say we had the same object we were working with and we wanted to print their name to the console we would just say bbum.name. So really great way for you to be able for you to just you know work with your code in a very natural less verbose manner.
Ok so we’ve talked about class design, showed you some properties, gone through the language a bit, gotten you familiar with that, let’s go back to this whole dynamic topic that I mentioned when we started things off. So Objective-C itself is an extremely dynamic language and it makes a lot of design patterns that make our system as powerful as it is possible in that dynamism. So I’m going to talk to you a bit about a couple challenges or a couple of situations that you might find yourself in or that we as framework developers find ourselves in and show you how Objective-C helps us deal with those.
This is probably a pretty common one. How many times have you wanted to, say subclass some common framework class, to add a couple of methods. Like maybe you wanted a string class that knew how to decrypt and encrypt data. Well you know in some other language or some other set of frameworks you might think to yourself ok well I’ve got a subclass, the string, I’m going to go ahead and add these methods to it and we’ll go ahead and do that. But then you’ve got this subtle problem of say in the case if we’re talking about Foundation, everyone else is still using a bunch of NSStrings for all of their stuff and you’d really prefer that they were using say your MJString in this case.
So what are you going to do if they’re all using all this different stuff? This is a minor problem. So this is where Objective-C categories come in and play a really powerful role. So categories allow you to mix in your own behavior at runtime. So you can seamlessly add methods to existing classes in the system and they just pick them up and you can begin using them no matter what, really, really powerful.
So in the case of our NSString, it’s got a bunch of methods defined on it. We might declare a category that we call say EncryptionAdditons and by declaring this category what this means is that at runtime these methods are going to be available for us on any NSString. So how do you actually do this?
What does it look like to implement this? Well it’s actually pretty simple. You just have to have some file in your project where you’ve got an @implementation block and you say @implementation, the name of the class that you want to be adding the category to, then the name of the category that you’re looking to add, in this case MJEncryptionAdditions. Now it’s important to note that categories mix in the methods that you add with the actual name space of the class itself.
So it’s really, really, really good practice for you to future proof yourself by putting some prefix at the beginning of these methods because who knows, 10 years from now AppKit might decide hey it’s a good idea to add encrypt and decrypt methods and you don’t want to deal with that conflict when it happens.
So make sure that you’ve, you know, adopt some best practice here and prefix these. Ok so now for us as framework developers we often end up with situations with our lot of view classes and NSTable is a great example where we’d really like you as developers to be able to customize the data that’s being displayed.
We want you to be able to customize how that data looks, how the user interacts with it like should they be able to select a row, should they be able to edit this data etc.And in a lot of other facilities your solution would be well clearly I’ve got to subclass a table and add all of these capabilities you know.
So I’ll define what the height of the row should be. I’ll define what the data source for all this information should be and I’ll have to have a subclass for every single table in my application which quickly ends up being not so fun. So this is not so good. We’d rather not go down this path.
What you’d really like is you’d really like some ability to have some class perhaps that manages the data and that your table you can talk to to get it. And another class maybe that’s more concerned with user interaction that can control how the users actually going to be interacting with that table and perhaps aspects of how that table is going to look. So again get the data from one of them and get that back and understand the user interaction from the other. So this is exactly what delegation is, an object oriented design pattern, is meant to handle.
And Delegation is not something that’s specific to Objective-C but it is something that you’re going to find all throughout the frameworks on both AppKit and UIKit and Foundation for that matter. And what Delegation really lets you do is customize the behavior of classes without having to subclass. And this could be anything from providing data from that class to actually say customizing the user interface, you know, how big should a row be etc., or lifecycle notifications. This is used say for NSURLDownload so hey go download this stuff and let me know when you’re done.
As a delegate you get notified of these sorts of activities. So let’s look at a couple common delegates that you’re probably going to be working with. So the first is the application delegate. On both iPhone and Mac OS X this is usually sort of the first class that you’re going to be starting off with. An application delegate is really designed to try to make sure that you can respond to both state changes and also provide customization and responsiveness around certain user events.
So by state changes I mean for example that an application if you set yourself up as its delegate, will say alright well did you implement any of these methods say like DidFinishLaunching, applicationDidHide, applicationShouldTerminate and it gives you a chance as the application developer to hook into these key points in your application’s lifecycle and be able to alter that behavior or influence that behavior in the way that you see fit.
And similarly for customization say you want to return a custom dock menu on Mac OS X, this is how you would do something like that. Now tableViews also make very strong use of delegation as you might have guessed from the example. But tableViews actually break up their delegates pattern basically into 2 delegates you can think of, one is your data source, this is the object that tables are lying on to provide the data to actually display and the other 1 is what it actually calls its delegate which is really more concerned with sort of user presentation sort of things like the height of the row, should a user be allowed to select the row, etc. And by setting yourself up as either the data source or the delegate of a tableView you have the ability to, say provide the row data or to you know alter that behavior. But how does Application for example, know that it can send applicationDidHide to your code? And how does the table know that it can actually ask the heightOfRow of one of your controllers?
Well it knows this by using respondsToSelector in Objective-C but noticing that what you’ve set yourself up as the delegate actually has implemented this method and can make use of this. But the next question now is how do you know what methods it is that you can make use when you’re the delegate of either of these objects? And that’s where protocols come into place in Objective-C. You can think of protocols basically as communication contracts between objects.
So this basically is just a list of methods and all it says is that say, hey I’m an NSApplication. Here’s my protocol of all the possible things that I might send to my delegate. And it’s just a very simple encapsulation of this so that you as an API consumer can make use of this. So let’s take a look of this.
We’ll use UITableViewDataSource as an example. So the first line you’ll notice here we’ve got @protocal UITableViewDataSource and then in angle brackets here we’ve got this <NSObject>. So @protocol just says hey, this is the beginning of a protocol. The next piece is just the actual name of that protocol and protocols can actually extend other protocols. In this case there’s an NSObjectProtocol which this data source is extending. Now you’re often not going to, if you want to say, declare your own protocol.
You probably wouldn’t normally add something like that but you will see this when you’re reading the code so I just wanted to cover that quickly. Now when you look at the next line here we’ve got this @required so as you might imagine, any method listed after that @required is required if you want to actually be someone who conforms to that protocol. Now you’ve got a @optional, any method that comes after that is optional for you to implement if you want to conform to that protocol.
And finally you simply end it off with a @end. So how do you actually conform to this protocol in the first place? How do you tell basically the compiler to check and make sure that you’ve implemented all of these required methods as being the data source for this UITableView?
Well in you’re @interface so in your header file, after your super class, so NSObject here just in angle brackets, you just say <UITableViewDataSource>. And if you have other protocols that you’d like to also conform to it would just be <UITableViewDataSource, next protocol, next protocol and you just end it with the angle brackets.
So what do you do in the actual implementation file? Well you just implement the methods. That’s all it takes. And that way when NSApplication or tableViews or any number other objects come around, you’ve had the compiler checking to know that you’ve actually implemented these, they’re going to ask your object, hey do you respond to this selector?
Well great, let me send you these messages and help customize how your user is working with the data or how the data is shown in the first place. And so all of these facilities really help to emphasize this model view controller way of working with the world. And our frameworks, perhaps more than any other platform that you work with, are really centered around this idea, this separation of concerns.
You know, your model error is going to be your data. You’ve got a control error, some controls might work with your models, some controls might be more concerned with what’s happening at your view ware and obviously you’ve got the presentation you have to worry about for the user.
So you’ve got the fidelity basically to have a strong interaction between these two without a bunch of needless sub-classing. And a view also has the ability to talk to let’s say a data controller who’s just going to turn around and who is specialized in talking to a model and so it really lets you bring this better specialization and this better separation of concerns to your development.
It really makes it rich and easy for you to work with these sorts of things. Alright so we’ve gone pretty quick and we’ve gone pretty wide here but we’ve given you a practical introduction to the language. You’ve seen the syntax, you’ve seen how to create a class, how to work with memory management on both Mac and iPhone. We’ve shown you some common design patterns you’re going to run into with the frameworks and we’ve shown you some of the dynamic behavior that’s really at the heart of Mac OS X and iPhone.
Now there’s a lot of sessions that are basically going to be for you to pick and choose from throughout the rest of the week but a couple that you might want to sit in on in particular just to see some of the excitement going on here, What’s New in Cocoa, it’s going to be everything that’s new on Mac OS X and in Mac OS X Snow Leopard in the AppKit and foundation frameworks. Always a great presentation and always worth seeing. You’ve also got, What’s New in Cocoa Touch. If you’re an iPhone programmer this is going to be all the media engineering detail about what’s actually new on iPhone and in UIKit to make use of there.
And finally our Objective-C runtime team has got a session on Wednesday Objective-C and Garbage Collection Advancements where they’re going to go into quite a bit of detail about what’s new in Objective-C and Snow Leopard as well as Garbage Collection. We’ve got some labs later on this week if you’d like to meet with our runtime team themselves and just chat them up, ask any questions you might have about the language. They’re available on Wednesday in the early morning and Friday at noon.
So thank you so much. If you have any questions, please feel free to drop me an email. My name is Michael Jurewitz and you can get me at [email protected]. We’ve got great documentation on Objective-C as a language so please make sure and feel free to check that out.