Working Effectively with Objective-C on iPhone OS

Session 113 WWDC 2010

Objective-C is the language of Cocoa Touch. Take an in-depth working tour of Objective-C, from properties and memory management, to integrating your existing C and C++ code with Objective-C. Examine design patterns, exception models, and other important considerations. A valuable session to hone your knowledge of the language.

Blaine Garst: Let's see.

Oh yeah, that's my name, Blaine Garst.

I'm Blaine Garst.

On my business card it says "Wizard of Runtimes," and so on the slides there's this little slot where you're supposed to put your title, and so I just kind of copy/pasted it there.

So, what does Wizard of Runtimes mean?

Well, I don't know.

I work on the runtimes for the Objective-C language, primarily.

And so, the runtimes is where all the coding happens.

And since I'm a programmer just like you guys, that's where I get to do my programming.

So, my programming helps you guys do your programming.

So, what's going to happen today is we're going to talk about Objective-C, and about how you folks can learn more about the language and some of the things behind the language, some of the things about the frameworks underneath it or above it, Cocoa Touch, and learning how to use it effectively.

So, the first thing we need to fix with the slide is we're going to talk about iOS, not iPhone OS.

In particular, the iOS platform applies to the iPad, the iPhone, the iPod touch.

You know, this is the description for what this session is supposed to cover.

And first of all, if we could raise the lights a little bit, I'd like to get a feel for among you folks, how many of you have yet to ship your first app?

Wow, OK. How many here have shipped maybe only 2 apps?

And I assume the rest of you might actually be a little more familiar with Objective-C than some of these folks.

Thanks, that's enough for the lights.

So, let me tell you what's going to happen.

We're going to take a tour, a little bit of a tour through Objective-C and some of the most effective ways to use Objective-C on Cocoa Touch, and I'm your tour guide.

So, as your tour guide, let me introduce myself a little bit more.

I've been programming since 1973.

I joined NeXT.

[ Applause ]

I joined NeXT Computer in 1990, and I had a little bit of experience at that point and I started doing things with my practice and experience.

I got to take some patterns of programming that I really enjoy and I put them into the language, so that my techniques of programming became standard practice.

In particular, I helped to add protocols to the Objective-C language.

[ Applause ]

This solved when adopted by Java, and they were pretty much copy/pasted into Java.

I have some quotes from Gosling on that.

That solved the client-server problem for like servers and stuff 'cause I could have this abstract design and stuff.

And so, I've been doing things like this ever since.

And so today, you're getting a tour by the tour guide.

You know, I might look like a horse because what I speak about in Objective-C is straight from the horse's mouth.

It doesn't get any better than this.

So, let's get started.

The iPad, the iPhone, these are awesome things to program.

There is so much fun.

It's so exciting to have all of this code out there that you can really play with them, make things happen on these devices.

These devices are just awesome.

To make things happen on these devices, you need to learn Objective-C.

It is the core, the center of how we make things happen, how you make GUI in particular happen, graphical user interfaces.

How you make Cocoa Touch do what you want to do.

There are other languages out there and my presumption is that you know at least one of these other languages because I'm not going to teach you Objective-C necessarily.

I'm going to teach you differences between what you know and what we do here what we do with Objective-C.

In particular, when you think about different languages, the first thing you think about is, well, you get syntax differences.

They've got different kinds of control flow operator, you know, operators and control flow primitives and things.

In particular, some languages have exceptions.

Some languages have these things called closures, which for Objective-C, we call blocks.

And if you know these patterns, what you really need to know is how do I do this pattern in this new language or this different language?

But beyond just the syntax, there's a lot of other stuff that has to go on when you do when you really need to make things happen.

You've got you know, how do you do math?

Do you have infinite precision numbers?

Nah, we usually have integers and floats, right, in some languages though.

But, you know, we have strings at different levels.

We have C strings, we've got these NSStrings.

There are structures versus objects for aggregating data.

If you have objects, you have different inheritance models, you know, the list goes on.

By the end of the list, when you talk about platform things, Memory Management is very much tied to the platform and languages are often tied to a platform.

And so, you have to learn more about the platform.

It's sort of beyond the language and you definitely need to learn about Memory Management on the iPhone.

I hear this is a little bit perplexing to some folks, and we're going to talk about that in particular.

So, to summarize what I just said, I'm going to try to map and go what you know in terms of familiar concepts with just a little bit of terminology difference and clear a little bit of syntax difference.

We're going to introduce and talk about Objective-C sort of uncommon ideas, things that have not quite made it to the mainstream, yet unless you consider Objective-C mainstream.

It is, I think, the number 10 most popular language now, at least by some definition.

So these are the things we're going to talk about to help you learn how to use our kits, UIKit, et cetera, to advantage.

In particular, I want to talk a little bit about what I consider be a pattern.

Now, there are books out there, design patterns and stuff.

And don't get worried, I'm not a boost kind of guy, but we will talk about patterns that make sense in terms of how we design things and how you have to use those.

So, that's what we're going to try to cover today.

Again, Objective-C is at the core of how you program the iPad, the iTouch or the iPad, the iPhone, and the iPod touch.

There are two other languages though, that you interoperate with all the time, and those are C and C++.

Now, the first topic I want to talk about is this thing called blocks.

Blocks has been added to the C language.

And through this thing called language inheritance, you get to use blocks also from Objective-C, which is a pure superset of C and C++ as well because that's what our compilers do.

And what blocks allow you to do is program from any language you want and stick blocks that use your programming language anywhere that a block is asked for.

So, it's sort of a glue facility of cross-languages to some extent.

So, let's talk about blocks.

I understand that this thing about multitasking is important to you guys, and so the background task identifier, if you want to learn how to totally do background tasking on the iPhone, you might have to learn this API.

It's got this block thing at the end, this void caret handler thing at the very end.

And so, actually it got talked about earlier in the week, so let's pick a different thing to talk about.

There's quite a lot to choose from here.

In fact, there's over a hundred APIs in iPhone OS 4 that use blocks, so I'm not going to pretend to go through any of them, honestly.

But this is kind of just a motivation as to, you know, why you might want to listen through this section.

So, this is what blocks look like for the C language.

We introduce this caret expression kind of syntax to mean sort of a local function, a local function expression.

You can write a function expression where you would write other expressions and you pass them as parameters for the most part.

In this case, what we're doing is we're going to send to some function called repeat, this little block pattern that says do a putc on d, presumably 10 times.

And the idea here is that d is going to go along with that.

You know, d is a local variable and you're going to get to use that within your block as it goes off and does things.

Now, blocks are actually not a very new concept.

That's what they look like in C.

They are called blocks in Ruby and in Smalltalk.

And in fact they were sort of invented in LISP in the scheme, actually, somewhere around 1973.

They were called closures in Scheme and there's a there's a lot of interest in this.

In fact, there's a new standard coming out for C++ and it's called C++0x.

It's in final committee draft or something like that.

And they have a construct called the lambda.

Now a lambda only fits into templates, for example, and that's the syntax you would use for the closure expression, but you can't actually use them you can't pass them directly to functions.

They're only useful within templates and they're different.

They're not full closures, they're a little different.

But the idea is coming along and we're happy and proud to provide to you blocks, you know, on the phone, as we've had them on Mac OS for a year or so.

So, here's another use of that repeat function, this time using some Objective-C code where we're just going to, you know, append some strings to a mutableString.

And the next box tells you how to implement that repeat function.

And so the syntax we use for blocks is that of function pointers.

Think function pointers with the caret symbol instead of the star and you'll understand the syntax of block pointers.

So, they're really block pointers just like we have function pointers, except to use that caret thing for the syntax.

And to use them, you just call them as if they were function pointers as I've shown here.

So, they're pretty easy to use, pretty easy to implement and work around.

And so that's why we use them all over the place.

They're useful, they're fun.

To summarize the syntax, we got a typical spot, sort of the function pointer return value slot or the return value specified.

You get some parameters some of the time and you got a body.

In this case, we're returning I don't know, it's a contrived example.

Another a thing we did though to make life easier, is we allow you to use abbreviated syntax.

And so when the compiler sees a return statement, it knows there has to be a return value.

And so, if there's no return statement in that body, then it can assume that it's a void, returning a void thing.

But in any case, even if you do return something, you don't have to specify that return value type.

So, the second line is exactly equivalent to the first line.

So, you don't have to say int, we infer this.

So the same is true, as I just said.

If you don't do a return at all, we assume void, so you don't have to type void.

And in the special case where you return void and have no parameters, you don't have to put the parameter list in either.

And so that's why you kind of see different syntaxes for these block literals.

And what this do is when a compiler encounters them, it creates a structure on the stack, which is the block object, and leaves you a pointer to this structure on the stack.

So, this is both fast and dangerous and so we have to be a little careful about these.

And we'll talk about that a little bit later.

So, blocks are also objects.

Even though stack-based things, you can send them messages.

Now, there's only a couple of messages that are of interest, and those are for primarily copy and release.

Because copy says make a perma make a copy it to the heap so that it can survive the stack frame of origin.

So what that allows us to do, allows you to do is write a block expression, pass it off to some API.

And if the API wants to keep a hold of it, pass that use, it can do a copy on it and preserve it.

And that copy costs a little extra cycles.

They have to alloc we have to allocate memory off the heap and copy it in there.

But sometimes you need to do that and sometimes you don't.

And so for the times you don't, we don't allocate heap storage for these things.

So, they're very efficient and, yeah, we like that.

We use them in many, many places.

We use them to enumerate collections.

We use them for what I call callback notifications.

There's often I'd like to say with networking code where you're going to go, you know, fetch URL in chunks, you know, and every chunk needs to be processed, and so you panned it.

Now you had a block in and every chunk is passed to your block, and that's a much nicer way to code it.

There's going to be some more talks later this week which give more examples of the code savings you get to use by just putting the codes you want in the block and just handing it off to the API that needs it later.

There's another whole facility called Grand Central Dispatch.

There're a couple of talks on that.

There's one actually later today.

I'll give references to this.

Where we talked about two things: One is to move code off the main thread, off the main dispatch queue, off the main run loop, whatever we call it nowadays.

Because if you try to do too much work there, then on the Mac, you get the spinning cursor, on the iPhone you get killed.

So, you don't want to do that.

So, you like you want to learn how to move work off the main thread.

And another thing, GCD is very powerful.

And in general, if you can figure out how to do things in parallel, GCD is the way to express that because what GCD does is optimize memory and battery life and all kinds of things to make sure you just give enough resources to get that job done under the circumstances.

And so you just code to GCD queues and the system kind of takes care of all the thread pooling and all the other kind of stuff going on.

It's very nice, there're talks later on, I'll give you a reference to those.

What I showed you on the other expressions is we capture the variable and we make a local sort of const copy in that block object.

Sometimes though, you need to mutate the variable.

And so, we actually introduced a new storage class keyword called under-under Block, for those cases where you need to pull a value back from something you sent off.

And I'm not going to talk about under-under Block here very much.

It's there, it's useful, it's somewhat intuitive, it works, and if you want to know more, we definitely will talk about that later to a great degree, on Friday in particular.

So in this case, we're going through a dictionary.

We're given a particular key and we want to return the value.

I'm sorry, we're given a value and we want to sort of find the key that was associated with that value, and so we return the key back to the caller.

So these are the two talks I've referenced.

There's Introducing Blocks and Grand Central Dispatch at 11:30 today, and on Friday we have Advanced Objective-C and Garbage Collection Techniques, so that's a little bit more of a Mac and a phone talk.

We cover material for both.

Here's another language construct, the for-in statement.

There's a lot of ways to go through an array.

Most people, we looked at code and many people are doing this objectAtIndex, objectAtIndex, objectAtIndex to go through arrays.

Arrays are the lingua franca for collections.

We get arrays back from many, many different APIs.

And going through arrays, we found that's taking up too many cycles.

So we introduced the language construct for-in that is backed by a particular protocol which you can adopt in your codes so that your objects can be you can use the for-in statement on your objects and have them, you know, rip through whatever kinds of items they might manage.

But in particular, this is a best practice because this is fast, fastest actually.

This is safest because in the middle of that iteration, we're actually checking to see if somebody changed the array underneath you or changed the dictionary underneath you, which can generally cause crashes.

And so we throw an exception when we detect a change so that, you know, at least you don't crash.

You get to figure out what you know, how that exception happens.

So that's, you know, that's a case of a good practice that we pulled into the language, and that's the kind of thing we do.

We try to make your job easier and better and more concise and clear and all that, all in one little language construct.

People ask me though, how do we get two values out of the for-in statement?

I couldn't figure out how.

Well, I didn't want to do it the way I figured it out.

We had a better way, and the better way is blocks.

So, if you need more than one value at a time out of an array or a dictionary, we've added block enumeration APIs and these are now the fastest way to get more than one value out.

So, in the case of arrays, I've illustrated how to get an array reversed with the index, and that's the fastest way to do it.

And then dictionaries, you often want to get the key and the value at the same time, and so this is the fastest way to do that.

These are also safe and are also extensible because, I'll show how to extend them later.

So anyway, this is best practice.

Let's go back to the phone in these three languages.

It turns out, there's another language on our system.

It's called Objective-C++.

And just as we add sort of an object layer on top of C in the Objective-C language, we add that same different object layer on top of C++ which has its own object, ideas about objects.

And so, let me tell you about Objective-C++ for just a minute, because if you already have a pile of C++ code, what you need to know is how to get the GUI to respond to it.

And so, what you typically do is you write a few files in Objective C++ and they can talk to your C++ code and they can talk to the GUI code and, well, I don't know, you can use Objective C++ for all your C++ code.

And so in this example, it's again contrived.

You signal that it's an Objective-C++ file by the .mm and a few other variations extension, and you sort of get to mix and match.

You can mix and match declarations, instance variables, member variables.

I haven't gotten the terminology slide yet.

So, in this case, I have a C++ class called My Engine and you can put a reference to your widget in there.

Equivalently, you can have your widget class and put your engine in there.

So, that's pretty useful.

So, even in Objective-C methods, you can use the throw statement from C++.

Objective-C has it's own @throw, @catch and @finally, but the exceptions underneath, the runtime implementation of them is the same across both of the languages.

And so you can throw from C++ and @catch from Objective-C, which just works.

The thing that you can't do is you can't sort of subclass a C++ class in Objective-C or vice versa.

You know, the object models are distinct.

So, you don't get operator overloading in Objective-C and you don't get selectors in C++.

So, it's sort of a marriage of convenience perhaps, I don't know.

Let's go on a little bit.

So, Objective-C has its own terminology for common concepts, and it's hard to present this any other way.

I mean, in Java C++, people talk about member variables.

We talk about instance variables or ivars.

A member function is a method or an instance method perhaps, or a dash method.

And unlike C++ and Java, they're always virtual and they're never final.

So, if you like those patterns, just do it by convention and you're just not going to get compiler support for that.

A static method is different in Objective-C.

In Objective-C, we sort of have a meta-class, and that the class actually is an object itself.

You can have messages and you can do inheritance in your plus methods, so you can call super within a plus method, which is kind of new, a little bit different.

But still, the idea of having a class method is not totally new, and so we have to have a terminology thing here even though the behavior is slightly different.

We have no equivalent to static variable as of yet at least.

So, we just use globals, it works.

What is called an interface, in other languages it's called a protocol, in Objective-C even though we wanted to call them @interface, but as you can see, what we call a class, we introduced a class using @interface, so we couldn't use the @interface keyword that long ago, but other people pick that up.

There is no operator new.

There are no stack objects.

Everything is allocated off the heap using an alloc method generally, or we have these things called convenience constructors, other plus methods can build you things.

I gave you an example already that NSMutableString string.

That string is a plus method that did a sort of a MutableString alloc init autorelease and return the result.

And finally, we have no explicit destructors.

We have something called the dealloc method.

But unlike destructors, you should never call the dealloc method yourself.

The dealloc method is called by release; when release figures out that the last release has happened, it calls dealloc.

So, don't treat deallocs like destructors.

You will get into a lot of trouble really quick if you try that.

So, let's do a little bit of review.

We have single inheritance of instance behavior.

So, we have NSObject, it's a got a hash function.

So, we're going to have an airplane and an animal.

We're going to have a fish and a bird and we're going to have a duck.

And what the language allows is multiple inheritance of abstract methods, and so in this case we have a swimmer that has one method called swim.

We have a flyer and a machine, and as you can see, the I'll see which one is it.

One of these duck that multiply inherits both swimmer and flyer effectively, and so this is the syntax we use to specify that.

Duck inherits from bird and implements the swimmer and the flyer protocols.

There's something new though.

Let's pretend that Apple provided animal and bird.

As I said, there was a hash method, there's also an isEqual method, isEqual is often overridden.

There's a method on NSObject called self.

And I've dimmed out self to sort of indicate that you really never re-implement that method.

You just inherit the implementation from NSObject.

And so as you get deeper in the class hierarchy, you get more and more behavior, more and more methods show up like you got a parents method out of animal and out of bird, you get a fly method.

And sometimes though well, and this is good.

This is what most languages do.

In your application, let's say you're trying to build a dragon.

And what would be nice, because you're going to animate these things, it would be nice if you could ask you're going to animate lots of objects including the Apple provided ones and yours.

It would be really nice, though, if you could just ask, is this object mythical?

Is this Apple provided object a mythical animal?

So, you'd like to add the isMythical method on to Apple's animal and you can do this.

You do this with something called a category.

Now category is never the term category is never it's not in the language.

It's just this funny syntax, and this is the funny syntax.

You declare an extension.

Here I labeled it MythicalExtra and you name a method, and you promise to implement this somewhere.

And so this is what the implementation would look like.

For animal, it's not mythical, return no.

But in your class, in your dragon class, you also implement isMythical, and in this case you return yes.

Now notice that bird is going to inherit animal's implementation so you can you know if the bird gets asked, are you mythical?

It's going to inherit the implementation on animal that you provided in your code.

So, let me talk about categories a little bit more.

So the add behavior to any class; use this judiciously.

I would not recommend just using isMythical here because you might borrow somebody else's code or Apple might insert an isMythical method or something.

And so, when you choose method names to extend, make sure they're really unique because we have a kind of a bug and we can get a little bit of collisions on these names.

Use them judiciously.

You can extend NSObject but it's not really recommended.

We don't really want a thousand methods on NSObject, it slows the whole system down a little bit.

So use them where you need to, but it's a very powerful technique.

They act like normal methods.

You can call super from them, in fact.

And with a little bit of code, you can also add data to sort of have kind of like a mix in model.

And the way you add data with categories, this thing we call associative references, and we'll talk about that on Friday.

It's API, and I don't want to get in to too much API here.

You can also use categories to split your implementation of a class across several files, because technically, as long as you're within an app or a framework, you actually have access to the private instance variables, again, a little dangerous here.

We don't allow that across frameworks, though.

These categories are very useful.

Let's talk about Memory Management.

So why? Well, if you don't do it well, you're going to crash.

Memory Management is about keeping objects around so you can use them when you need them.

And if you don't keep them around, you're going to crash.

On the other hand, if you keep them around forever, your app gets more and more memory, it gets sluggish, it gets sluggish, and eventually that's going to cause it to crash in a way itself.

And so, Memory Management means using just the right amount of memory and no more.

So, the Cocoa Touch system that you use, the retain, release, autorelease thing, was designed for use on a 8-megabyte system, like 20 years ago.

And, you know, we had to be very memory efficient back then, and that's also true on the phone.

So, you know, some things change and some things don't change.

So, it's been around for a while.

So Memory Management, unfortunately, the design of it starts at I mean, it starts at the design phase.

If you just go build an app and you throw retains around like crazy and then you have to come back and clean it up, you can be in trouble because you have to think through your object patterns at the design phase, and you learn that on your second app probably.

So, the way you design it is you design object ownership as a directed acyclic graph.

And the ownership of objects comes from a very simple pattern, and that is we have few methods that transfer ownership.

Alloc and init transfer ownership of an object to their receiver.

A copy method does the same thing and there are a few plus new APIs that also do that.

But otherwise, APIs do not transfer ownership.

You just kind of use them because the objects are around.

And as you saw in the if you did, I hope you did.

As you saw in Monday's afternoon talk, the static LLVM Static Analyzer can help you with your retains and releases by showing you where you got it wrong, and that's a very cool tool.

The Instrument application can also show you where you got leaks, and that also was demo'd.

In particular the heap shot command within the memory, within the allocation instrument can help you detect unused memory that's just kind of hanging around.

So, let's talk about that directed acyclic graph a little bit.

So, here's one of them, and it's kind of like a lattice.

You know, pointers just keep pointing down.

And I've illustrated the reference counts, you know, the number of retains in each object this way.

And let's say that these are all of the references on the system right now.

So, what happens when that top reference to part of that graph goes way, the top object loses its ref count to zero then it lets go of its things on down.

Now, did everybody see the pattern go down?

Let's try that again.

When we let go of that top reference, that top object goes to zero, it lets go of things it owns.

They let go of what they own.

They let go of what they own, et cetera.

And once you have retain count zero object, it gets reclaimed and so your graph goes way.

This is what you want to happen.

If you accidentally set up a back pointer, an up pointer that is retained, then what happens when you let go of that top reference is the top node goes from ref count 2 to ref count 1.

It sticks around forever, not what you want.

I think it's obvious what happens if you fail to do a retain count of an object and it goes away prematurely, that's also bad.

So, the simple rules to make Memory Management work well for you are that at the design phase for every instance variable you decide, do I retain this one or do I not?

Is it an up pointer?

So, the general pattern is you retain your instance variables.

Only those up links get non-retained.

And when you go to do assignments, you have to release the old value on retain instance variables, and send the retain message to the new value coming in unless the new value came from like one of those methods, init, or copy or new.

Finally, sometimes if you're asked to provide a result and you have to create a result on the fly, you stick it in the autorelease pool if you don't keep it yourself, and so that your caller just seize it and it will go away after a little bit of time.

Let me explain how autorelease pools work.

So at the bottom of your stack, there's a little bit of code that's going to get an event or something and call your code.

It's going to call the process event.

So, at the beginning, we created well, we have a stack with some local variables and so we create a pool and we create and we get an event from somewhere.

Now, in all likelihood, the event is also held in that autorelease pool, but I'm not illustrating that.

And so we start calling process.

And let's say process needs a new date.

It's going to call NSDate date and get some value out of that and compute.

We passed the event on up the stack.

So inside NSDate, there's some code that looks a lot like this.

This is the alloc init autorelease pattern.

That's very common.

You guys should probably learn that one as well.

So, at the very beginning, at the alloc init time, what happens is sort of the stack holds a reference, a retain count reference to the object D, that date, and then we send autorelease to it.

And what that does is it transfers ownership down into the autorelease pool, which is secretly around.

You know, it's just there.

When the date routine returns, you know, D is returned on the stack, it gets processed and used, you know, it gets the value out of it.

And when that frame goes away, the autorelease pool is left with the reference to that date.

It's still hanging around even though nobody knows about it anymore.

But eventually the pool is drained, which is how we get rid of the objects within a pool and get rid of the pool itself.

And so, the pool goes away and everything within it goes away and that data object goes away and there's no memory loss, and so that's how autorelease pools work.

You can actually create them and use them yourself when you know you're going to be creating a lot of objects, a lot of autorelease objects.

You can create a pool and then drain it yourself, and that's a well understood Memory Management technique that you use when tuning for performance.

Let's talk about accessors.

In Cocoa, we have had this pattern for 18 years of balance and setBalance as the way we named our accessors.

You have a backing instance variable called int balance, and in the implementation you implement these methods.

There's just a lot of typing of that balance word, right?

So, to kind of make this simpler, what we introduced was something called properties.

And so to replace that code I just showed you, this is what you need to do.

You say @property int balance.

And then in your implementation, you say @synthesize balance, and because we now have the same runtime running in the Simulator, as you have on the iPhone, we get to make use of this Objective-C 2 feature such if that's all you have to do.

The compiler will synthesize the instance variable in your class and it will synthesize the implementations of that setter and getter.

In fact, though, we noticed, well, why do even need the @synthesize?

And so, in Xcode 4, in the new LLVM compiler that comes with it [ Applause ]

it's on by default.

So, let's talk a little bit more.

To get to that new facility though, you have to pass a special flag to the compiler.

It's there but it's not quite integrated in the IDE the way we would like it to be.

It will be though.

So, let's talk about properties a little bit more specifically.

Properties have attribute, so these things in parenthesis.

In this case, we're going to say perhaps balance was a read-only in customobject, and in a subclass of customobject called supercustom, we want to make it read-write, that is allowed.

Otherwise, whatever attribute you see sticks.

It's an unchangeable property of the property unchangeable attribute.

Let's talk about what those all are about.

So, if you don't like our names, if you don't like set and if you like get or whatever, you can actually, in that parenthesized section, you know, provide your own custom method names.

The other the other thing you could do as an attribute is particular if you're talking about an object property, is you have to tell the compiler whether it's a retained object, whether it's simply assigned.

Assigned is sort of a synonym for non-retained, at least in the retain-release world.

And the other option, the key option, is copy.

Well, we'll get to copyable mutable copy kinds of things later.

But it's very important and copy implies retain, by the way.

So, that's how you get values into your object, you know, but you can pass a mutable string in because it's going to be copy that we copied into an immutable string and stored.

Nonatomic is a keyword that sort of means single-threaded.

It's kind of performance.

There are some slight safety issues with it but it's very prevalent on the iPhone, on iOS.

But it's generally considered harmless.

We'd prefer that you not use it though because as dispatch queues and things go on, things are becoming more multithreaded all the time.

Finally, I already talked about read-only and read-write.

The idea with that property is you don't have to trust the compiler to do any of the work at all.

You can use an app property and fully implement it.

You can have your secretBalance, you can write your setter and getter.

In this case, maybe you had, you know, a different instance variable than something called balance.

And so I illustrated that.

And that pattern is common enough though that we actually support that in the compiler by simply saying @synthesize balance=secretBalance.

And if you didn't even provide secretBalance, you could do that also and the compiler would synthesize a secretBalance instance variable.

So it's use it you know as much as you want, use it for everything, use it for some other things.

Finally, if you're going to be using that @property by default, there are some rare cases where you don't want to provide an implementation at all because you know how to use forwarding, because there's another hook you can use.

And in those cases, you have to use @dynamic or you will be required to use @dynamic to tell the compiler to not synthesize things.

So, that's a keyword that's going to get a little more use, I think, in the future.

Again, advanced garbage collection, Advanced Objective-C and Garbage Collection talk is where you're going to learn about that.

Now, I cheated a little bit.

I didn't talk about properties of objects.

This is a pattern you have to write, would have to write yourself in order to implement a correct property object attribute, I'm sorry, correct object property.

In particular, you need to synchronize, you need to make sure that 2 threads aren't trying to set at the same time and one of them gets half the result and the other one doesn't, or a getter is trying to come in and give a value that's being changed, being released underneath it.

And so, it's actually kind of complicated.

And so, we actually want you to use that synthesize, wants you to you have the compiler in runtime do the hard work for you on this.

And in particular, you do need to write a little piece of code in the dealloc method to get rid of that object.

So, here you can just send title the release message, which is typical.

I also showed what we call our .syntax.

Self.title = nil is some shorthand for saying set title to nil.

The compiler just turns that self.title into self set title to nil.

And that's the .syntax works, you know, everywhere pretty much.

And but it's just shorthand for sending Objective-C messages around.

We don't really do the compiler really doesn't, you know, spit out the code to do it in line.

It's just it's just a almost a macro for calling calling the message explicitly.

So, let me talk a little bit more about Cocoa patterns.

So, selectors are kind of fun, they're not really in any other language.

Selectors are data structures that represent sort of the slot name.

There are some API's you can get to, to get the actual string that's used.

It's foo: bar: whatever, at the moment.

They're not really too interesting.

The id object type, that was the original object type and the only object type when Objective-C was invented.

It allows any message to be sent to it, without warning, by the compiler, even ones that aren't going to be implemented.

And we have invented or it was invented, this method called respondsToSelector, and so in this case we have syntax for naming a selector on the fly called @selector here.

We're going to ask, does object respond to the selector fred?

And if so, we're going to send fred to that object.

Now that's kind of squirrelly you might think, except within UIKit we use it all the time.

Let me show you where.

We use it for delegates.

You know, an Interface Builder where you hook up a delegate to a control, this is what's going on.

You implement a particular method that you want done at a particular piece of time.

I pulled this one out of the action sheet thing.

So, suppose you needed to overwrite and do something special when the willPresentActionSheet message would come up.

And so, you implement just that method and, you know somewhere you set the delegate.

And normally, you kind of do that in Interface Builder, but you can do it by hand also.

And again, the .delegate is our .syntax for saying UIActionSheet setDelegate to self.

So, this is your part on how to do delegation.

Inside or not inside, but UIKit actually declares a set of methods as optional methods within a protocol.

Optional is not in other languages.

Optional says these are sometimes implemented.

This is the syntax for them.

And so, UIActionSheet declares its delegate as implementing this protocol.

And so when you set the delegate, you know, your class let's back up.

Your class implements UIActionSheetDelegate.

And so you get type safety when you do that setDelegate method.

And inside UIKit, when it comes time to ask to present that sheet, it goes respondsToSelector, you know, whatever that meant that was, willPresentActionSheet.

And if your object implements it, then it will go send that to you.

Or in other time, it's going to say didPresentActionSheet and it goes respondsToSelector and you don't implement that, so it says ah, don't bother, skip it.

And so, respondsToSelector is a very powerful mechanism to, you know, add optional behavior to things.

And it simplifies your life because you could put a lot of code in the delegate and not have to do subclassing and figure out how to do subclassing properly.

So it's a pattern that we use a lot.

Target action uses selectors all the time also.

Let's talk about class clusters.

A class cluster is sort of an abstract class, like NSString, then that's all you want to know about strings is the things in NSString itself, even though under the covers what we do is we actually have several implementations.

They're concrete secret private implementations and you don't care, except if you know how to build a string yourself, we tell you how to do that by implementing sort of a key method in the abstract class.

So, we don't typically subclass NSString to add behavior to it.

You know, you don't tell it to go do other things too much, we use categories for that.

So there're categories for, say, open this string as a file rather than subclassing it, the sting to be a special file kind of thing.

So categories let's you add behavior to things like even NSString, and Apple does that.

And you get to subclass primarily for representational reasons.

There is, and we hear about you see in the documentation this thing called property lists.

And property lists are value classes, including collections.

So we have strings and data, we have NSNumbers and we have dictionaries and dates.

And so those are the property list classes.

They are easily transcribed and onto disc or into HTML or, you know, many different formats.

And the key thing about them is they're immutable.

They're a value class.

You can use them freely across all those threads that dispatch is offering you because, you know, there's not going to be no contention on them.

Another pattern or this isn't really a pattern, this is just part of the system.

A pattern we have is sort of our mutable value pattern.

Several of those classes, plus a couple of others and not all of them, we have this abstract layer of immutability.

Strings and arrays, you can't change.

Data, you can't change.

And so we have for each one of them an inheritance, and we have a mutable version of them which you can change obviously.

So when we designed these, we said we want to have a mutableCopy method, and clearly a mutableCopy method when passed to a mutableString should give you a mutableString back.

And similarly, if you sent mutableCopy to an NSString, you should get a mutable version back out of it.

So, that led us to conclude that when you send copy to an NSDictionary, you should get an immutable dictionary out of it.

But surprisingly, when you send copy to a mutable dictionary, you get an immutable value out of it.

That's just the way we do things.

It's a little surprising, you need to know this.

We have protocols for both of those.

And so you see the protocols adopted.

NSObject for example does not implement the copying protocol, so your objects do not have to implement copying although NSObject does actually participate and actually does implement copy just as a helper for those classes that do.

So, I talked about the terminology for common concepts.

I talked about our most important uncommon ideas, you know, blocks and properties, categories.

I touched on some of the other little little things that are different about our language and how we use it.

And finally, we talked about patterns a little bit.

So, the related sessions of interest are Introducing Blocks and Grand Central Dispatch where you learn how to move work off of your queue, that's later today at 11:30.

API design for Cocoa and Cocoa Touch, we have a review committee for APIs inside Apple to make sure they come out looking just right.

And API design is hard.

And so, Ali Ozer is going to give this talk on Thursday at 4:30.

I highly recommend it.

Ali is just the best guy for this.

Advanced Objective-C and Garbage Collection Techniques is going to be given by my colleague, Greg Parker, on Friday at 11:30.

We'll talk about how blocks really get copied to the heap and, you know, some of the fun stuff that goes on.

And for more information, you can contact your developer, our developer tools evangelist, Michael Jurewitz.

He calls me Blainecus so I call him Michaelopolis.

Apple, Inc. AAPL
1 Infinite Loop Cupertino CA 95014 US