Essentials • 52:15
Objective-C is the language of choice for development on Mac OS X and iPhone OS. Understanding Objective-C, how it works, and how it supports development on both platforms is key to creating great applications. Learn all about Objective-C, advantages of the dynamic runtime, and compare its design patterns to other common programming languages. If you're new to Objective-C or need a good refresher, this session is for you.
Speaker: Bill Bumgarner
Unlisted on Apple Developer site
Downloads from Apple
Transcript
This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.
Welcome. Just getting started with Objective-C, a simple, elegant, and dynamic language. I'm Bill Bumgarner. I manage the runtime team. We're responsible for Objective-C, garbage collection, blocks, and a handful of other things. And I really do want to welcome you to Mac OS X and iPhone OS programming. I know a lot of you are new to this. It's an exciting platform. There's a lot of movement in this. There's a lot of new things. Yet at the same time, I think you'll find that it's also a very mature platform. You can rely on the features, you can rely on the language.
In particular, I know that when you're learning something, if you learn like I do, you often learn by example. And to that end, what we're going to do is we're actually going to look at an example. Excuse me for a second. And I want to show you what is Objective-C.
I want to give you a foundation with which you can read Objective-C effectively and you can understand it, and then show you that Objective-C is a foundation for a lot of patterns in Mac OS X and on the iPhone, and really give you a set of tools that you can go forth into the other sessions throughout the week and very quickly digest and internalize the information. I don't have enough time to do a full language survey. I really don't have enough time to effectively teach you all of Objective-C. But with that, let's move on.
What is Objective-C? Well, let's do a little bit of a guided tour here. I'm going to do a little high level intro, and then we're going to get into some code. So Objective-C is a language that's been around quite a while. 1984, I believe, was when StepStone, the company that created Objective-C, was actually created. It's a set of syntactic extensions to C. It's literally extensions. It doesn't try to change the meaning of C. There's a couple of additional types that you'll find in the language and you'll see throughout the code. It does have class methods. They're not like Java static methods.
As well, it's like C++ in that it separates the interface from the implementation, so your implementation will be kind of more private, and your interface, the part that other people will use or you'll use in other places in your code, is separated out. It has a single inheritance model, which is a little bit simpler. But it does have a feature called protocols, which Java borrowed as interfaces.
Which allows you to actually share interfaces across multiple classes. There are categories which give you the ability to extend existing classes. Subdivide your implementation. Method invocation. Objective-C is different than C++ or other languages. On the garbage, or on, I should say, memory management, there are two different styles of memory management you can choose when you're programming for OS X. On the iPhone, you use reference counting only. On OS X, you can use reference counting or garbage collection.
There's also a feature called Properties, which is relatively new to the language. It was added in the last few years, which allow you to syntactically express what items are data in your objects. There's also a dynamic runtime underneath all of this. It's actually active. It runs with your application. It's very important, and we'll get to that in a moment. So, let's talk about grokking Objective-C.
And when I said learn by example, I mean quite literally. If you have your computer open, you have the dev tools installed. If you were to open the example, developer examples, app kit, iSpend, most of the code is going to come directly from that. You'll see some differences on screen because, well, no one programs on 1024 by 768, but I have to make slides in that size.
So, first, Objective-C. It is C. It's a set of extensions to C, and this is probably the first Hello World program ever written, back in '70-something. And if you were to look in your project, which will look something like this, and open up, you'll see that there is a main file. And if you look in that main file in Objective-C in a Cocoa app on the iPhone, you'd see something very similar, not quite the same. You'll see it's C. Calls the main, passes control to Cocoa.
Now, you probably built and run the app. It comes up. It shows a window on the screen. It's a document window. So you're thinking, okay, let's go figure out how this thing works. Let's look at the document class. And you'll see there's a mydocument.im file. And if you were to open that up and look at it, there'll be something like this.
And if we look at this, we can see that there are some differences in Objective-C than C. In particular, we can see there's some of the new types. So in this case, we see I've highlighted some of them here. There's nil. Nil is the empty object. It's like null in C. But it's nil so that the compiler can differentiate between an empty object and a pointer to nowhere or nothing, I should say. Oh, sorry. I went one forward. too fast.
There's also an ID, which is a generic object reference. It's a typeless reference to some object somewhere. It's kind of like a void pointer, but this gives the compiler the ability to know that, oh, you've got a reference to some object somewhere. You can message it. You can do things with it, but you don't know what type it is.
There's also Boolean type. Objective-C defines bool, all uppercase. It is different than bool, all lowercase. Of course, this is C, so there's some wonderfully intuitive details like that. There's a yes and a no that are defined, and I will mention it again. It's different than bool, the lowercase one, and when you convert between the two, you have to be careful.
As well, Objective-C is an object-oriented language. What's the first object you ever encounter in any object-oriented language? A String class. In Objective-C there's NSString. This encapsulates strings. Now, this gets into something very important. When we talk about a tour of language like this on a platform like Mac OS X and the iPhone, it's impossible to separate the language from the implementation details. So when we talk about NSString, that's really not part of the language. There is this convenient syntax for creating these things inline and on the fly, but really NSString is part of the foundation.
However, you know, you've got to write code quick, so here's a convenience for you. You'll see the @ sign a lot in Objective-C. It's often used to introduce Objective-C-isms into code. And of course, it's object-oriented, so we declare methods. This is an init method. It has a dash in front of it because it's an instance method. And this is the initialize method, which has a plus in front of it because it's a class method.
And if you'll notice, there's this Add Implementation My Document, which again gets back to the separation of implementation and interface. So, at implementation implies that there's probably gonna be an add interface somewhere. And sure enough, if we go back to our project, we'll see there's a my document.h file. It's being C or being derived from C. You'll have .h files, which are the parts that are included into other things to allow those other things to use that interface. So, double clicking my document, we'll see a standard class declaration here.
In particular, @interface, my document, the class name, inherits from the class NSDocument. So we're creating a subclass of the NSDocument class. And of course, we can declare instance variables. Now, instance variables are kind of an implementation detail. Yet, because we're in C, it's often very important for the compiler to know exactly how things are laid out in memory. And thus, this implementation detail usually has to be exposed.
So you'll see the instance variable declarations in the interfaces. And then we also can declare a lot of methods. In this case, we're declaring three instance methods and a class method. Now, what's interesting about method declaration is you might have noticed, well, yes, instance, class, I forgot about these transitions.
You might have noticed in your source file, if you have it up on screen, that these methods are not declared. The reason why is because they're actually declared in a superclass somewhere. And because my document's implementation of them is not really that interesting. It's not something that the designer of my document felt needed to be called out. So they're inherited from somewhere. You typically won't see things like this, their declarations repeated. So moving along, we now see we've got three methods here.
And we have transactions. This is a method that returns a reference to an NSArray, takes no arguments. Objective-C interleaves arguments with the method names. So we see set transactions colon as a method in here. The colon means there's going to be an argument. And when you get two arguments, like this one, you'll see that the name of the method is interleaved with the actual argumentation. So this method is insert transactions at indexes. That's the whole name, the full name, and nothing but the name. Names of methods, they're called selectors.
So, these are three selectors on our object, three methods that it implements. You can't drop parts of them. So, again, and this is something I'll repeat a little bit because I've taught a lot of Objective-C over the years, and this comes up for people that are coming to the language. A method's name is its selector, and it's very important to know that in Objective-C, there is a type, an SEL, which represents a method name.
And you'll see it quite often. For example, the NSObject class, which is the base class used throughout Cocoa and iPhone programming, implements a method called responseToSelector. It takes a selector as an argument. It returns a Boolean if that object responds to that selector. This means it's very easy to ask objects these kinds of questions. Because it's so easy, you'll see certain design patterns fall out of that that rely upon that. For example, delegation, target action, the way the thread class works, the way operations work, a number of other classes.
And again, set transactions: if our class were to implement all of these, set transactions: set transactions: of type: and finally, set transactions: of type: in context:. Normally we don't say the colons, but for specificity I'll mention them. These are all distinct selectors. In Objective-C, you can't drop parts of the selector. That becomes a different method. So moving on here, we saw that our document class was doing a lot of stuff with transactions.
Let's have a look at the transaction class. The declaration of this looks a little bit different. As a matter of fact, I think if I don't remember correctly, the declaration of it doesn't contain anything like the method declarations we saw before. It also has this little thing up at the top, NSCoding, in brackets, angle brackets. This is a protocol.
This is telling the compiler and declaring that this class is going to implement whatever is promised by the protocol. In this case, a protocol is a reusable interface. It is a collection of methods, a set of method declarations. And what we are saying when we declare that our class implements a protocol is that we are promising to provide an implementation of those methods. Now, furthermore, we can also ask the instances of the class later, hey, do you conform to this protocol? So protocols can also have optional methods and required methods in their declarations.
So when you say that you implement a particular protocol, like the UI table view data source on your class, you must provide those first two methods. And you can optionally provide any of a number of other methods that are declared in the add optional section to further change the interaction between a table view and your object.
And it's important to note @Required is the default. If you looked at the NS coding declaration, there was no @Required there. It's cuz all the methods are required. So, protocols. There's something you can, when you declare a class, you can say that the class implements a protocol, and you are promising to provide an implementation of the required methods in that protocol.
You can also specify multiple protocols. You can also declare a protocol that implements another protocol. So you're basically promising that anything that uses that protocol or implements that protocol will have to implement all required methods in whatever protocol that protocol uses. And you'll see there's this NSObject protocol. There's actually a number of protocols on the system that are pretty common. That's because in Objective-C, the base class is more or less advisory. That is, you can write your own root class if you want to. Almost no one ever does.
If you do, you'd have to pretty much reinvent everything in the NSObject protocol, which, again, the language being inseparable from the system itself is a lot of work. Some of the other protocols you'll find on the platform in the foundation is NSCopying, NSMutableCopying. NSCopying for creating a copy of an object. MutableCopying for creating a copy of the object where that copy could be changed later. NSLocking for integration with threading. And NSFastEnumeration for taking advantage of the four enumeration of collections of objects.
It's interesting to note that the iPhone OS actually uses protocols a lot more than Cocoa programming. It's one of the few areas where there is some difference. In particular, you'll see things like the application delegate, table view data sources, all these things declared as protocols. That was actually done because it allows the compiler to give you better warnings and errors when you mess up a type or something like that. It's literally to provide better checking.
Now, there's something else interesting when you look at this project. You see there's this mydocument.h, mydocument.m. But then there's also a couple of other My Document file names in here. We have these two pasteboard ones. That's because the implementer of this application decided, let's subdivide the implementation of My Document for organizational purposes and pull the pasteboard functionality out and put them in different files. And they did that by using Objective-C categories. A category allows you to take a collection of methods and add it to an existing class.
So, in this case, we're declaring a category called Pasteboard that extends the My Document class. It adds a number of methods to it. And if we look at the implementation file, We'll actually see the implementations of those methods in an Add Implementation block that, again, declares a pasteboard category on the My Document class.
Now, what's interesting about this, and I worked hard to make sure I got a screenshot of this in, because this is a new feature in the Xcode you have with you called Open Quickly, and it is terribly cool. If you were to hit Shift-Command-D and type nsthread, you'd see a list something like this. And if you open nsthread.h, you'll see that it actually has in its API a declaration of a category on NSObject called nsthread perform additions. What this is actually doing is adding additional functionality to the NSObject class.
Now, you can add additional functionality to NSObject if you want to as well. It's not--the barrier is not at, say, framework boundaries. So if you have some particular thing that you want every object in your entire application, no matter who wrote it, to do, you could add it to NSObject if you want. It's a feature to be used with care from a design perspective, as you can probably imagine.
And again, NSThread has an implementation something like this for adding those methods. So categories, they allow you to add methods to existing classes, kinda like class extensions in C#. But Java doesn't do this. You can add methods to classes outside of your project. You cannot add instance variables.
It can't affect the storage of the class. And this is because, of course, if you change, say, the storage in a C program, change the layout of a structure, and you have other structures that are dependent on that, then everything has to be recompiled or else the layout gets all messed up and you get really interesting crashes. However, on Snow Leopard, you can add associative references. You can use associative references to associate a piece of data with an instance or a class, which gives an instance variables-like feature.
You can also, you can access instance variables though. So if the class declares instance variables, you can access them from within your categories. Do this with care. It's likely that the class has some logic related to the state management. There may also be some limitations to doing this, depending on what version of the operating system you're linking with and whether or not the instance variable you're trying to get to is inside whatever you're compiling or is in, say, a system-provided framework or some other piece of code. So let's step away from the syntax part of this a little bit, the declarative part, and let's actually look at the method calling mechanism itself.
Objective-C uses a Smalltalk-like syntax for calling methods. It's not the functional style that you're familiar with from Java or C#. In particular, You can call class methods. It's bracket, the target, and then some thing to do. So in this case, we're calling the array method on the NS immutable array class. And if you were to look at the NSArray declaration, you would see a method declared something like this.
Returns an object, doesn't take any arguments. Similarly, we can call instance methods. Same syntax. In this case, we're calling an instance method on self. Self is like this. It's a reference to whatever object is currently executing the current method. So we're calling the writable pasteboard types method on the instance, our self.
And its declaration would look like this. I think it was actually a couple slides ago. Similarly, we can call an instance method on some random object reference. We're calling the containsObject:, or just containsObject method, passing one argument, type, on the object types.
[Transcript missing]
It's a single flat namespace for all methods. That is, there is a one namespace for all selectors, all method names in your application.
There is no type-based dispatch. So what that means is when you declare a method, if you declare the same method name twice and you declare it with different types for the arguments, then you're very likely going to get compiler warnings. So generally, you won't see that done anywhere in Cocoa. I think there's one case where it's done.
So nil, the empty object, it eats messages silently. If you try to call a method on nil, it's just nothing's going to happen. As long as the type sort of looks like an object reference, it's an integer or a float or something like that, you're generally going to get a zero back if you try to take the return value from it. But that behavior is not really well specified, and if you look in the documentation, it will warn against relying upon that. So, there's no null pointer exception in Objective-C.
And again, Objective-C, the arguments are always interleaved with the method name, both for declarations and for invocations. And it's important to note that Objective-C doesn't have keyword arguments that are so common in scripting languages. So you could say the arguments are named, but they're not keywords. The order is critical. Change the order, you get a different method. Drop something, different method.
Add something, different method. And Objective-C, being born out of C, does support variable number of arguments. So you've got the vararg style, dot, dot, dot, declaration available. And you can parse those lists. Generally don't see this a lot. You'll see it within a string class. You'll see it with some of the collection classes.
Which, now that we've got some syntax in hand, and we have method invocation in hand, we can talk about memory management. We're going to talk about non-GC memory management. And frankly, C does not provide a lot of inspiration on this front. If you have programmed C, you'll know that a lot of times you have to go look at the documentation and you either have to free the thing returned to you or don't free it or send it off somewhere else to get cleaned up or, you know, nil it out or whatever.
I mean, it's a hodgepodge. And originally, Objective-C was actually done the same way. And then in about 19--early '90s or so, when the APIs that were provided in the system kind of expanded and became more of a foundation, quite literally called the foundation, Objective-C move to reference counting. And reference counting is really dead simple. It's so simple, it's very easy to make a mistake. If you want to keep something around, retain it. Literally call the retain method. If you don't want it anymore, call release.
And a method might typically, you think, look like this. However, the problem here is that we're returning something we've retained because we want it to stay around once we've returned it, so whoever called us can make a decision about what they want to do with it. But now we've kind of said, okay, well, I'm passing ownership to you.
Well, what if that thing calling us doesn't want ownership? What if they just wanted to poke at my stash of goods a little bit and then forget about it? We need some way of delaying that release, some way of kind of saying, we're going to make sure the object stays around for a while, and we're going to kind of throw it out there, and if anyone else wants it, you have an opportunity to grab it before it goes away forever. This led to the introduction of auto-release pools.
And what an auto-release pool does is it's literally, you can think of it as a bucket. You throw the object in the bucket and it sticks around and eventually the bucket gets They're automatically created and cleared for you when you're running a run loop. So if you're running the run loop on the phone, you're running a run loop in Cocoa, the main event loop, or you're running a run loop in a thread you've created, the auto-release pools will be managed as a part of the run loop. You can create them manually if you want to.
There's an auto-release pool per thread, generally. If you have a run loop, it's created automatically. If not, you can create one if you want. When you call retain or you call release or you call the auto-release method, which I'll show in a second, the auto-release throws it into the auto-release pool for the current thread.
What that means, though, is when you're doing multi-threaded programming, you must make sure that you retain the object for the duration of passing it between two threads. You can never rely on an auto-release pool to keep an object around long enough for a thread pass to be safe.
The auto-release pool, like everything else, is fully documented. I actually point the documentation out because it's actually quite good on this subject. Fills in a lot of more detail. and revisiting the retrieveGoods method that we wrote before. Now we can modify this so we first retain my stash of goods, and then we auto-release it before returning it.
And what this means is the caller can poke at my stash of goods, do whatever it wants to, and if it wants to keep it, it retains it, and if it does it, it does nothing. And then when we get to the bottom of the event loop, we get to whenever the auto-release pool for that thread is drained, then that reference to my stash of goods will go away if my stash of goods was replaced in my stash box. At some point in time, then the one that was pulled out of there earlier will get destroyed.
So memory management rules for non-GC, again, this is the definition of it. You own any object you create. That means you've retained it. You can create objects via methods that begin with ALAC New or Copy. I'm going to go through this quickly. It's all documented. ALAC New, Copy, Mutable Copy. Those are things that create retained stuff. Everything else generally returns an auto-released or non-retained reference.
And again, non-retained does not always mean auto-released. If you own an object, you have to release it. And don't ever directly deallocate an object. Because something else may have retained it. Maybe the design of some framework you're using has changed, and now it's retaining things when you don't expect it.
So just don't call deallocate directly. If you don't own an object, don't release it. If you call retain, you've got to balance it with a release or an auto-release. Retains can lead to cycles. So if A retains B, B retains C, and C retains A, that's a cycle. It's gotta be broken. They're hard to debug. Or, but there's good tools for that.
Or you could just use Garbage Collection. And under Garbage Collection, All this stuff goes away. And there's some great sessions on using Garbage Collection later in the week. Unfortunately, Garbage Collection is a Mac OS X only technology. So if you're on the phone, be careful with retains and releases. There's also an advanced session on Friday which will go into this in much, much greater detail. Plus, there's the instrument session, which I highly recommend. Instruments is an incredible debugging and performance analysis tool.
Okay, so let's go back to our transaction class for a second. Let's have a look at these properties. Now, when you're doing object-oriented programming, what's one of the reasons you do object-oriented programming? It's so you can encapsulate things in objects. Generally, you're encapsulating data and functionality, but in this case, we're looking at some data. A transaction object has a bunch of data associated with it. It has an amount, a date, a description, things like that. Well, let's look at what this class would look like before properties.
Before properties, you'd have pretty much two methods for each piece of data. You'd have a setter, set amount, set date, set description string, and a getter, amount, date, description string. Pretty repetitive. Now, you know a little bit about the memory management stuff. What you don't see here is any information to developers using this class as to how to manage the memory appropriately. They don't know if the date is gonna be retained, which should be, but they don't know that.
They don't know if the description string is gonna be copied, so they wouldn't know if, well, what happens if I pass a mutable string in, something that could change later? Is that gonna be bad? So this is how it was for a long, long time. In the last few years, we revisited this and we captured The standard Cocoa setter-gitter pattern into something we call properties.
What properties allow you to do is to take these very typical repetitive method pairs and reduce them to a single declaration per pair. And at the same time, give users of your class, including yourself, more information to work with to successfully use that class. So looking at amount, we can replace set amount and amount with an at property double amount. Properties declaring the type, it's double, its name is amount.
And similarly, we can do the same thing for date. Now, dates aren't mutable, so we don't need to worry about copying it. And we're gonna say we're gonna retain this thing so that clients of our code knows that if they pass us a date, we're gonna keep it around.
So set description string and description string again. We can replace it with a property. In this case, we're going to say that we copy the string being passed in. So clients of our class know that whatever they pass to us, we're gonna be copying it so they don't have to worry about mutating it later.
And we're also going to declare that this property is non-atomic. That means that the act of setting something via this property, the act of setting the description string, isn't going to do anything to protect against thread-based conflict, more or less. And now our class declaration is a little bit simpler. And more importantly, not only is it simpler, it's also much more precise.
But we didn't stop with just the declaration side. Properties also provide tools for helping you with the implementation of getting and setting data on your classes. So in particular, we can synthesize a property, which means in the implementation, in this case the implementation of transaction, we are going to synthesize the description string property. Which means the compiler will actually create set description string and description string methods for us automatically, and it's going to use the instance variable underbar description string as the storage.
So now not only have we reduced the amount of code we've had to write and the least buggy lines of code are ones you don't write at all, but we've also taken advantage of the compiler's ability to generate these setters and getters that are exactly correct. So you don't have to worry about bugs in the storage. And now we are in the torturing a cat phase of the session.
You can also choose to write it all yourself. In the case of transaction, the amount, the set amount methods, they're custom. They have some custom logic in them, so the implementer of it just wrote everything themselves. As well, you can actually choose to mix and match. So for the date property, we actually have a custom set date method because it does some additional logic, but we're letting the compiler synthesize the date method itself, the getter.
Finally, the other thing you can do with properties, which is pretty cool, you can say @dynamic. And this gets back to the dynamic nature of Objective-C. What you're telling the compiler is that even though you're not providing an implementation of the methods at this time, you will ensure that the implementation comes into existence at runtime before or during the first time any one of those properties is accessed.
So, there's one other aspect of properties. We also added something we call the dot syntax in Leopard, which allows easy access to properties. And it works for non-property setters and getters, too. So you don't have to convert stuff to properties to use the dot. And when you see APIs that use set something and something as the standard setters and getters, you can just use a dot. And literally, these two implementations of the addService method are equivalent. In every way, outside of the minor syntactic difference.
So, properties. It's a syntactic encapsulation of the standard Cocoa Setter-Gitter pattern, as well as the iPhone OS Setter-Gitter. It also declares the memory management intentions, so it provides more information to clients of the class than just the method declarations themselves. It ensures compatibility with Cocoa patterns. And again, when we talk about the language, the language in this case is inseparable from the APIs of the system. And by using properties, you are ensuring that your classes are going to be compatible with various mechanisms in Cocoa, like key value coding, key value observation, bindings, and a number of other patterns.
You can automatically synthesize parts of the implementation using properties. And those synthesized bits of functionality can be atomic, meaning that under threading, if you pound on a property setter from two threads at the same time with atomic, it won't crash. It might not do quite the right thing, but it won't crash. Whereas non-atomic's a little more efficient, not quite as safe. You'll see on the iPhone, most of the UI kit uses non-atomic throughout because the user interface is intended to only be used from the main thread.
On the, what we call, modern runtime, which is the runtime that's on the iPhone OS, as well as the 64-bit runtime on Leopard and Snow Leopard, you can actually synthesize the instance variable storage. And this will take care of basically creating the slots to store the data away. When you go this route, though, at the moment, you can't actually directly access the instance variables.
So it's actually interesting because this allows you to both synthesize the storage so you don't have to worry about that part, but it also means that there's no way someone can go in through a back door to change that value out from under you. So if you have some custom logic or whatever that you need to do, this is a way to guarantee that it gets called at this time.
And this brings us to the dynamic runtime. So we've talked about the syntax, we've talked about memory management, method invocation. All of which is built on top of this dynamic runtime. And it's important to know that every method call in Objective-C will be dispatched by the runtime. It will go through the runtime dispatchers. It will go through the runtime mechanisms. No exceptions.
And that in and of itself is very much an enabling technology. It's a pattern or a feature that drives implementation or drives the patterns of functionality across the rest of the frameworks. In particular, that runtime is what enables the ability to introspect object capabilities very easily. So you can ask objects, "Hey, can you do this? Can you do that?" And you'll see this in Cocoa a lot.
You'll see a pattern called delegation. Which allows Object A to ask Object B, "Hey, do you care about, do you want to do something about this? Okay, go do something about it." Which allows you to avoid subclassing in a lot of cases. It allows for simpler implementation patterns.
This also means that dynamic loading, when you dynamically load a chunk of code, you can extend existing classes through the use of categories. And because every dispatch is going to go through that runtime, those additional methods that you've added to those classes will be visible. And of course, because of introspection and the ability for the runtime to go, yes, that object does that, no, it doesn't do that, that means that this additional functionality will immediately become visible. There's no hidden stuff. There's no static finals. There's no optimizer, say, running that's going to fold or inline a method on you.
You can also dynamically construct implementation as needed. Now, this is not something you're typically going to do when you're writing the code, but it is a pattern that is very useful to be aware of because there's a lot of functionality on the system that uses it. There's a full runtime provided in the Objective-C runtime itself, a C-based runtime, so you can go and you can actually construct class on the fly if you want to. With the at dynamic properties, there's this method, resolve instance method. Go read the documentation on that and you can actually see how to dynamically construct the setter or the getter for a property. And in particular, this dynamic runtime enables very rich proxying and bridging solutions.
So when we talk about this enabling technology above the dynamic runtime, and we talk about things like categories and properties and protocols, These are pervasively used throughout Cocoa and throughout the iPhone OS. You'll see patterns like the delegation, the key value coding, key value observation, Cocoa bindings, even things like Interface Builder itself, which Interface Builder is allowing you to graphically configure a bunch of objects for your user interface. When you hit save, it doesn't generate code.
It uses the NS coding protocol to archive a binary copy of that configuration of the user interface that can then use the NS coding protocol at runtime to pull that back in, connect everything back up. Again, connecting everything, that's a lot of introspection, key value coding, the bindings is using key value observation, etc.
Core Data, which uses dynamic property generation and actually will generate classes at runtime for your models. Again, it allows Core Data to be a much simpler implementation, while at the same time achieving levels of performance that are just really frankly astonishing. And I encourage you to go to Cocoa Fundamentals. Even if you're an iPhone OS programmer, if it fits into your schedule, go to Cocoa Fundamentals, because so much of the Cocoa Fundamentals is universal to the iPhone. And the What's New in Core Data session is very interesting as well.
So when we talk about the introspection and delegation, this is a pattern that is pervasive enough I really wanted to call it out. When an application is launched, the NS application, the one shared application object that's created in every Cocoa application as it launches, it has a delegate.
And you'll typically set that delegate up in Interface Builder. You can do it in code if you want. And the first thing the application does is it asks its delegate, "Hey, delegate, do you respond to the selector? Application will finish launching." And if it does, it calls it. Now, what's interesting about this is this means as a developer, you don't have to subclass the application class.
You can have kind of an application controller thing that maybe does some application control stuff and maintains some other state in your app that can also help customize the launching of an application. And you'll see there's probably, I think, close to a dozen of these delegate methods for application alone. Some other classes that have delegates, the file manager for handling files, file creation and file errors, NSKeyedArchiver, which is a part of the NSCoding protocol.
This is actually interesting because this allows you to do things like if you, say, rewrite your app for a 2.0, you can use the NSKeyedArchiver delegate to help convert your 1.0 data without actually having to subclass and greatly change the Cocoa coding mechanism. The XML parser, there's a number of others.
At the application layer, NSWindow is very much like NSApplication. You can use the delegates to do things like change the way the window resize behavior works. If you want a window that's always four by three, you could do the math in the delegate method to ensure that that's the case.
NSTableView, NSImage, NSText, all of these things have these delegates that allow you to control their behavior without subclassing. And the same thing with the XML parser. If you're new to Objective-C, there's a number of other applications that allow you to do things like change the way the window resize behavior works. If you want a window that's always four by three, you could do the math in the delegate method to ensure that that's the case. And the same is true on the phone.
So when we talk about dynamic loading, there's an NSBundle class. And this is just a little snippet of code that actually shows loading a bundle. And I wanted to call this out briefly because Objective-C, one thing it doesn't have is namespaces. It's something that a lot of people have requested over the years. We are definitely aware of the need for namespaces. But we frankly haven't come up with what we would consider to be an elegant enough solution to provide at this point.
You need to keep that in mind. Avoid namespace conflicts. They can be problematic. Typically, it's done by having a prefix. If you notice, all the Cocoa classes have NS. All the iPhone classes have UI, Core Animation, CA. So pick some free prefix. I would suggest three letters because I don't think any of Apple's stuff uses three letters.
And when we talk about dynamically generated implementation, this is not a piece of code that I want to go into in terribly much detail, but it's rather advanced. It's also not a piece of code that I would expect that many of you are ever going to need to write. However, I wanted to call it out because this is a demonstration of the use of the Objective-C API underneath. So you'll see things like selector manipulation and adding methods, etc. And these are bits of functionality that are actually leveraged quite a bit in the Cocoa frameworks.
So when we talk about proxying and bridging, this is another pattern that you will see often. For example, the scripting bridge. Which allows basically you to generate an Objective-C class whose API talks via Apple script through, not really actually Apple script, via Apple event to an application. And it generates those classes on the fly from that application scripting dictionary.
So this actually allows you to treat, say, iTunes as an object, as an instance of some class. The bridges between Objective-C and scripting languages, it turns out Objective-C is a very natural language to bridge to other languages because of this dynamic runtime. They all use these APIs. In particular, they use something called Bridge Support, which is a bunch of metadata on the disk that describes all the APIs in the system.
And the Cocoa Development Using Scripting session later on in the week is actually going to cover a lot of this information in detail. If this is of interest, I highly recommend that you go see that. And finally, proxying. So what proxying allows you to do is literally create an object that's a proxy, that's a stand-in for another object.
And that stand-in can capture all the method calls that would normally go to the real object and do something about it. In the case of key value observation, every time you say use Cocoa bindings or you're using core data, it's actually creating a proxy for your object such that any time the setter or the getter is called via protocol or via properties or via the methods, the key value observation proxy will pick that up and give other parts of your application notification that something's about to be read, about to change, or that it did change. Distributed Objects, which is a technology that's built into the foundation, uses proxies, and it literally enables a local proxy, a local object.
[Transcript missing]
So, Objective-C.
It's a small set of additions to C, as you've seen. And the focus is really on simple and consistent. And through that, I believe, elegant. I've been doing this for a while. It's built on top of a dynamic runtime. That dynamic runtime is both there for your use as well as leveraged heavily by the frameworks that you'll be using.
It uses a very simple object model. You have single inheritance. You don't have type-based dispatch. But this also means that you don't have things like namespace mangling and other complexities of debugging. You can reuse interfaces through the use of protocols, which you've seen are used quite often in the Cocoa and on the iPhone.
It has a very simple method dispatch mechanism. Every single method goes through that dispatcher. There's no type-based dispatch. There are selectors. Selectors are method names. Selectors are first class type in Objective-C, and you will see them often. There are labs. We will actually be in the labs pretty much all week long. So if you want to find us, come down, look for the team.
We're happy to answer any questions you have. If you see us in the hallways, pull us aside. We're quite happy to help. There's official lab times as well for the Objective-C 2.0 lab, and as well as garbage collection lab, which I don't know why it wasn't on there. There's some publications.
Thank you, Bill. I'm going to go ahead and introduce you to the next section of the session. Objective-C is C. There's the classic Kernegan and Ritchie, the original C programming language book, or C for Dummies. It's another very good book, actually. As well, there's lots and lots of documentation on your systems already.
The Objective-C 2.0 programming language is an excellent document, though. Object-oriented programming in Objective-C is just another great way to use object-oriented programming. It's a really nice piece of introduction to object-oriented programming, too. There's the Cocoa Fundamentals Guide and the iPhone OS Programming Guide, which of course are all built on top of the foundations provided by Objective-C.
There's some very, very useful mailing lists as well. There's the CocoaDev and the OBSI-Lang list. Sorry, I call it OBSI-Dev. These lists are on Apple's list server. The community of people in there are extremely helpful. If you have questions, bring them to these lists and you'll find the answers very, very quickly. The archives are all online as well, and there's extensive resources in the archives.
These are wonderful just reference materials as well as being a really warm and friendly community of people. Useful people. There's one of them right here, Michael Jurowicz, the seventh. There's also Derek Horn. And, of course, plenty of documentation in the Mac Dev Center and the iPhone Dev Center. With that, I would like to open this up for some QA.