Configure player

Close

WWDC Index does not host video files

If you have access to video files, you can configure a URL pattern to be used in a video player.

URL pattern

preview

Use any of these variables in your URL pattern, the pattern is stored in your browsers' local storage.

$id
ID of session: wwdc2000-126
$eventId
ID of event: wwdc2000
$eventContentId
ID of session without event part: 126
$eventShortId
Shortened ID of event: wwdc00
$year
Year of session: 2000
$extension
Extension of original filename: mov
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: ...

WWDC00 • Session 126

Cocoa Overview

Mac OS • 1:01:44

This session provides an overview of the powerful, object-oriented Cocoa APIs for creating full-featured desktop applications for Mac OS X. The Cocoa APIs range from low-level utility, system interaction, internationalization, Internet, and platform independence classes to a rich set of user interface widgets, including a powerful and extensible text system.

Speakers: Becky Willrich, Mike Ferris, Ali Ozer

Unlisted on Apple Developer site

Transcript

This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.

Ladies and gentlemen, please welcome Mac OS X Applications Technology Manager, David Wright. Thank you. Good afternoon. Welcome to session 126, Cocoa Overview. I'm really excited to see how many people are here because this technology in this session is amazing. In 1991, when I was in college, I was taking a windowing programming class, and I was working with X windows most of the time. So seeing what they were trying to do to get inheritance to go was pretty interesting, especially to someone who was barely grasping pointers at the time.

And then we had a couple weeks where we were playing with other windowing systems, and there was this black cube, and we were told to do a programming assignment on that. So just, can I get a clap of hands of how many of you have used Cocoa or played with Interface Builder or Project Builder? Yeah? I think half, but my sound meter isn't always accurate. Well, I was playing with this program called Interface Builder. You tell it what objects you want to work with, and then you draw this line, and it hooks up all this messaging. And I was just tripping out, because it was amazing. I've never seen something like that.

So then I went on to be a Mac programmer, and in 1988, I was assigned to work on the setup assistant for Mac OS X, which is completely written in Cocoa. And here I was back using this amazing development environment. So I have no problems. I represent Carbon and Cocoa. Both are great.

But Cocoa is like a true pleasure. It really is like driving this amazing car that, you know, you just want to use it as soon as you can. So without further delay, I want to introduce you to the Cocoa API. I want to introduce Becky Willrich from the Cocoa Application Development team. Please give her a warm welcome. Thanks, David.

Gee, Toto, I don't think we're in Redwood City anymore. So hi, my name's Becky Willrich, and I'm here to talk to you about the Cocoa development environment. We're going to start out by looking briefly at what Cocoa is. I'm going to show you a little bit about how you develop a Cocoa application, and then we're going to spend most of our time talking about the core concepts within Cocoa.

So, by the time you leave this session, you should be able to identify the main pieces within Cocoa. That includes listing the core classes involved in every Cocoa application. We're also going to talk some about the basic abstractions used inside of Cocoa. Now, I would love to go into the details of Project Builder and Interface Builder. These are amazing development tools. In particular, if you've never seen IB, you have just got to go to the session.

PB and IB both have sessions of their own, and I encourage you to go to those because we're just not going to have time to cover them here. So hopefully you've all seen a diagram that looks more or less like this from the keynotes. It's an example of the OS X architecture stack. And it's pretty easy to see where Cocoa fits in. We're one of those development environments right up there at the top.

So what is Cocoa? Cocoa is a set of frameworks designed to work together for application development. So far, so good. It's fully featured. It has support for all of the basic paradigms that you expect to see inside of an application environment. So support for things like cut and paste, event handling, full widget set, full text system, all of that is there.

There are also several powerful abstractions we export to make it easier for you to write your application. But here's the main thing. When someone asks you, "What is Cocoa? What makes Cocoa different from the rest of the stack?" There's the answer. Cocoa is objects. This is what differentiates us from Carbon. This is what makes us unique on this stack.

So what do I mean by that? What I mean is that Cocoa is a set of fully object-oriented frameworks. These frameworks have been designed and implemented in objects from the ground up. The APIs are exported in object-oriented languages, both Java and Objective-C, and all the classes have been designed with the intent that you, the developer, be able to simply extend them and use them easily.

So, as I was preparing for this talk, I was thinking, oh my gosh, what am I going to tell these people, right? Here, you're all Mac programmers, you've already learned one very large API, how can I convince you that Cocoa is worth looking at? So, this is what I came up with.

We're just going to see, take a poll, we're going to do the little plazometer thing, and see if you can guess how many lines of code are inside of TextEdit. TextEdit is a small Cocoa application that does text editing, it's sort of the Cocoa world's equivalent of simple text.

So, just clap when you think I've reached the right level. How many of you think it's under 5,000 lines of code? twenty thousand? You guys already know the answer to this don't you? Alright fine. Yes! Text edit is an example application. It's under five thousand lines of code. It comes in at thirty three hundred.

By comparison, simple text is seventeen thousand, eight hundred. Over five times as large. You can prove this to yourself by looking on your DP4 CD where you can find the text edit code under system examples... or system developer examples and just take a look for yourself. Well that's all very well and good. Text edit is, as I said, an example program. What about a real program? What about mail? Mail, I hope you've seen in some of the keynotes that Steve has done.

He showed it at the Macworld keynote in January. It is the premier Cocoa app on the system. And it's a full mail client. Let's start from the other end. How many think it's over a million lines? Between a half million and one million. Between a hundred thousand and a half million.

This isn't going to work so well. Between 20,000 and 100,000. You're right. Mail comes in at 65,000 lines of code, which to me is pretty impressive. I mean, here we've got a full deployment application. If you attended some of the keynotes yesterday, you were hearing line counts on the orders of three-quarter million or 1.2 million for a full production app.

So let's drill a little further into those 65,000 lines of code and mail. Of those 65,000 lines, over a quarter of them are just comments. So we come out at under 50,000 lines of actual production code. Of those, you can further break it down into a third of them going into the application itself. The other two-thirds is going into a framework which is shared across several applications. So not only is Mail a very small application, but we're actually reusing most of the code.

So, to answer the question, why Cocoa? The answer is that objects are powerful. And this is going to read pretty much like, you know, the textbook speech on object-oriented programming. Objects are easy to configure, they're easy to extend via subclassing and other simple abstractions. You can export many powerful abstractions and notions using an object architecture, and it is ideal for code reuse. The end result is that you, the developer, can do more with less code.

So when we were going over those line counts, I was talking to a coworker of mine, Mike Ferris. And he said, you know, 3,300 lines is actually quite a bit. We've got a lot of support for loading different file extensions and that kind of thing. And we could actually do text edit in quite a few-- "I think I can give you text edit in 50 lines." I said, "Yeah, right." He said, "No, really." And we're going to take him up on that challenge here today. So with that, I'm going to introduce Mike Ferris and turn the stage over to him.

Is my mic live here? Can you all hear me? Okay. All right, so we're going to just start by creating a brand new project in Project Builder. See, we're up on the screen here. And today I'm going to create a document-based application using Java. So we'll choose the Java document-based application template. And let's just call this TextEdit Lite.

OK. So what we start out with here is, as you can see, a couple of source files and a few resources. We have two user interface files, which are interface builder nib files. And just to prove that we're not starting with a whole bunch of canned code, I'll show you all the code that we start with here. This is the little piece of C code that gets us bootstrapped so that we can double-click this Java application.

And then this is the document subclass, the subclass of the NSDocument object that we start out with by default. So that's going to represent our document in the running application? Exactly. We'll have one instance of this object for each open document. OK. And you can see that we've started out with just some boilerplate code. There's a few methods where we're expected to fill some stuff in here. That's not going to leave you with very many lines. No. We've started out with, what, 30 or so already. So I'm already behind.

So first, though, let's do the interface. And we're going to build the interface in Interface Builder. We've started out with a nib file that's going to be instantiated once per document. It's called mydocument.nib. So we'll just open that up real quick in Interface Builder. So this is going to be the window that's going to display the document to the user? Exactly. OK. Now we'll get rid of the little placeholder text here. And instead, we're going to add a text object off of the palette.

And let's bring the inspector up here and configure this just a little bit. We'll take the border away, turn on undo, should always be able to undo. And let's make it so that when the window changes size, this text view will change size as well. And then let's make it fill the window too. Okay, so starting to look a little bit like a text editor here.

Now, the other thing that we're going to need is access to our text view from our code. So let's go to the classes tab in Interface Builder here. And in our document class, we've already got a pointer to the window, but let's add another one. So let's add this instance variable that we'll just call myTextView.

And we'll go back to the Instances tab, and let's actually make that connection. So we've told Interface Builder that we have this instance variable called myTextView, and that we've also told it that this is the TextView. So that's how the document's going to be able to reach its interface? Exactly.

What'll happen is when the document loads its interface, part of the loading of this interface file is going to cause the instance variable myTextView to be automatically initialized to point to the TextView that came out of the nib. So when you say load the interface file, I mean, are you generating code here? No, actually, Interface Builder files are not code. We're not a code generator. In fact, what you're manipulating here is all live objects, and then what happens when you save this is it's just going to serialize all those objects.

Just like Java serialization, that kind of thing? Basically. Okay. So, all right, we're done with the interface. We've made our connection. We've set up our TextView. Now, I'm not going to sit here and let you watch me type. So instead, I've got kind of a pre-done version of this class, and we'll just get rid of the one that we came with here.

And instead, let's go and add in the one that I've already got in my Documents folder here. Now, you better walk us through this so that, you know, we know you're not loading libraries on the side or anything. You think I'm going to be sneaky? All right, well, let's put this in here, and then I'll show you.

Now, in fact, this is almost identical to the code that we started with. And what I've added, I've added a couple of instance variables. First, we see the MyTextView instance variable, which is what we hooked up in Interface Builder. And then we also have the TextStorage instance variable. The TextStorage class provides the backing store for our text.

All right. Now, mostly this is all the same, except when we get down to about this point. Let's start from the bottom. And we're just going to, I'm not going to walk you through this line by line, but briefly, these two methods are concerned with saving and loading the file. I think I saw those in the template. Yeah, these two were there and empty in the template that we started with. I've just filled them in. Okay.

And notice that we're not running save panels, we're not writing files, we're not doing any of this. All that you really have to do in a document app is be able to provide the data that will go on the disk and take the data that was on the disk and initialize from it. So, we're just working at the level of a bunch of bytes that came off the disk. We don't know how they came off the disk. They're just here.

Now, the next method that we started with in the template, just empty, and which I've filled in, is this one. This method gets called whenever the document loads its interface. So we're going to take that opportunity to make sure that the text view is displaying the text that we loaded from the disk or whatever. So we'll just take that opportunity to sync everything up. And we do that with a new method that I've added.

So this is the one brand new method I've added to this class. And all it does is it makes sure that the text view is showing the contents of that text storage object. So you're just kind of updating the backing store in the front end and keeping everything in sync. Exactly. Now, that's all the code.

And we're almost ready to run this thing. But first we need to make sure that the application knows what kind of files that it's going to deal with. We haven't told it that it's an RTF editor yet. So we're going to go into the target editor. And in Project Builder, this is where you edit your info P list stuff.

And if you've read some of that system overview book, you'll know that the info P list is where your application is going to advertise what file types it understands. Now, Finder uses this information to know what app to launch when you double-click something. In addition, the Cocoa document system uses it.

as well to know what kind of documents this app understands. So this is just sort of publishing what kind of types of document you want to handle. Right. And so we give it an abstract type name, which would just be something basically unique. We can also tell it what file extensions this type is associated with and also what Mac OS types.

Okay, so we're kind of hooking up the extension with the type creator, with mime type, all of that. Right. Rolled together. Okay. So and then the last thing in here is that in Cocoa Apps you have a key that tells you what class in your application is to be used to display these documents. And in our case it's this my document class that we are going to use. So that's it.

And now I'm going to go ahead and build and run this thing. So you're telling me you're done? I am done. I didn't see any code in there to control the menus or -- The menus -- oh look, I didn't save the interface folder file. Okay. So the menus are already -- The menu is already all hooked up in the template, and you get basically a standard menu bar when you create this thing. And that includes all sorts of menu items for dealing with cut, copy, paste, and all the rest of that kind of stuff. Well, we'll just see, won't we? Okay. Why don't you take project builder off the back of that? Oh yes, let's minimize that.

Okay, so here's our program. Okay, now when we were preparing for this, I created a list of some simple text features that I would really like to see in this text editor. So if we could have the slides back on one of these. Over there. Ah, thank you.

Let's start out real simple. Just prove to me that you can enter rich text up there. Okay, well let's go to the font panel for that. Cocoa has a built-in font panel that all apps can make use of, and of course it's integrated with the text system. So we can do things like change the font size and change the font.

And can you embed a feature? Yeah, there we go. Yeah, maybe we can set that to be italic. Okay. What about pasteboard, clipboard kind of stuff? Can you copy and paste? Sure, of course. So let's copy that and maybe we can paste it. Maybe we can paste it a few more times.

Okay, how about ruler support? Well, Cocoa also has a built-in ruler, which also is integrated with the text system. So we can just tell it, "Show me the ruler." And here it is. You can see that we have tab stops and margin settings. We can set the alignment. We can do all the things you'd expect to do from a ruler.

All right, how about colored text? I didn't see you hook up any color panel or anything. The Cocoa color panel also is integrated with the text system, so we can just drag colors off and set the color of the text. We can use the apply button, too. Okay. Most of the code you wrote had to do with saving and opening documents, so let's just make sure that all works. Okay.

So we can save. You'll notice that we have a sheet already. The document system runs saved. It can save panels of sheets like it should, so you get that all just automatically. We can just type in a file name and tell it to save. Okay. And you'll notice that the title bar updated to show that we've now got a named document. Okay. Why don't you close and reopen that just to make sure we can reload files. Okay.

There it is. There it is, and we just open it back up. OK. Undo. Probably need code for undo. Well, we actually, if you were paying attention, I turned on the undo in the interface builder file there. And the text system supports undo. In itself, but also when the text system lives inside of a document, it'll automatically hook itself up to the document's undo, and we'll get per document undo in our text system automatically. So I'm just making a couple changes here so we'll have something to undo. And you can see that I can do undo. I can do multiple levels of undo and redo. Hmm.

Let's try again. There we go. All right, that one's not really fair. I mean, ligatures and kerning you'd only really expect on a real publishing package. Well, if you look closely, we actually have ligatures already. The text system will use ligatures when it's appropriate, just automatically. You can also tell it that you'd like it not to use even the default ligatures, for example, and so we can split that fi apart.

We also have support for track kerning. So you can go ahead and just tighten that line up a little bit. It's getting harder. Spell checking. Spell checking. Well, turns out Cocoa also has an integrated spell checker, but to show that, we're going to have to actually have a misspelling.

OK. Whoops. And so we can just bring up the spell panel. Just bring up the spell panel. Exactly. Now this spell panel, like a lot of this other stuff, is pre-integrated with the text system, but it's also available for you to use in your own ways in your Cocoa app. So we can just go ahead and tell it to find, and it found our word, and it even knows how it's supposed to be spelled, so we can just correct that and move on.

OK. The Cocoa Text System is based on Unicode and is also integrated with the TSM input management stuff in Mac OS X. All I really need to do is go up here and change to Japanese. Now I have to apologize if this turns out to be a swear word or something. I don't actually know Japanese.

It looks like the font panel automatically picked a Japanese font for you there. Right. The text system knows what characters can be displayed in what fonts. If you are typing in Helvetica, say, and start typing some Japanese characters that can't be displayed in Helvetica, it's going to go out and look for another font which is similar to Helvetica and use that instead.

A recent documents menu. That can't be standard in the template. All right. Well, in order to show that, let me actually do a save as for this guy. So we'll have played with a couple of different documents here. So we'll just save this guy as test two. And now you get an open recent menu just automatically, and it's hooked up so that any time a document is opened or saved, that document will end up in the open recents menu for your application. So I can go over to the original one that we saved earlier and just open that up that way. Wow.

You got me. However, there is one important piece of every application left that I'm sure you haven't hooked up. What's that? Do you have an about box? Sure. The template comes with a standard about box, which of course you can replace if you like, but we have an about box.

That's it. Actually, it was 51 if you count the blank lines, I think. Okay. All right. Thank you very much. No problem. If you are not now convinced that Cocoa can do a lot for you, I give up. I don't know what else to say. I do have a couple points I want to make about that demo. Obviously, we are leveraging a couple different subsystems within Cocoa pretty hard.

Those subsystems are the document architecture and the text subsystem. Both of those are subsystems of several different classes designed to work with each other, all of them designed for subclassability and ease of use. If you are interested in them, I highly recommend that you come to the in-depth talk on Thursday afternoon, because Mike is going to be back talking about the document architecture, and my manager, Ali, is going to be speaking on the text subsystem.

The other thing I want to point out is that this is not a 4GL kind of thing where you get to take it out of the box and use it exactly as is, or you can't use it for your purposes. To give an example of that, the text subsystem is used by a couple different applications in DP4 and OSX. One is Mail, which uses it pretty much without modification.

Mail just wants to be able to edit rich text for your mail. Another one is an HTML editor that's used by the WebObjects folks. There, what they've done is they've heavily subclassed and extended the text subsystem, which is designed to work, as you saw, with RTF, but they have been able to extend it to create a full HTML editor.

All right, moving on, we're going to start talking about the pieces inside of Cocoa now. There are basically two components inside of Cocoa: Foundation and AppKit. And you can see how they lay here. Foundation is the lower level. It provides all the basic object infrastructure that you would expect. It does not use graphics at all. And then the AppKit sits above Foundation and also above Quartz, OpenGL, QuickTime, the entire application services stack.

So I'm going to spend a moment now talking about Foundation in detail. As I said, Foundation establishes the basic object paradigms within the Cocoa application. That includes all the basic classes for storing and manipulating data as objects. It lives below the graphics layer, and you can't actually use Foundation without the kit to produce something, a faceless application, something that needs to run in the background and never presents a window to the user.

So if you look at the classes inside of Foundation, they basically fall into these three categories. You have basic classes for storing data and for holding the data together in collections like arrays and dictionaries. Then you have a set of classes that are designed to act as object abstractions on top of the operating system, so you don't have to drop down to the POSIX layer or to lower layers in the operating system. And then finally, we have support for internationalization and localization.

So let's just start with the storage classes. Very briefly, the leafs are NSValue, which stores a numeric value, NSString, which stores a string, and NSData, which can be used to store an arbitrary bag of bytes. Those can be combined together into collections, like NSArray, which is simply an array of objects, or NSDictionary, which stores the objects in key-value pairs. All these classes can be combined together in what we call a property list.

And what's nice about property lists is having combined together this fairly complex tree of objects, you can then write it out as a plain text format and read it back in very simply. There is also an XML format in addition to the traditional ASCII format that's available through Core Foundation.

And what we've found historically is that property lists are ideal as a small, flexible data store for data throughout the system. Mike alluded to the Info.plist. That's a property list and is used to configure your application and expose it, explain how it should be represented to Finder and to the other applications on the system.

We also use the property list to store all of our user preferences. There are a number of small, Unix-ish configuration files that are expressed as XML property lists. And we even use it as a communication medium on the pasteboard. Property lists are really cool, and I'd love to tell you more about it still, but I'm not going to have time, and so I'm just going to point you to the core foundation session where we talk about property lists in greater detail.

Okay, the next category is OS installation. There are a number of classes there for handling things like file access. I have a list up there. Process management, so you can keep track of the different threads in your application. You can fork off additional tasks, and you can get the information that the operating system has collected about your process. We also have mechanisms in there for cross-thread and cross-process communication, and I've just listed two.

Internationalization. We consider internationalization and localization extremely important in Cocoa, and for that reason we've included it in the basic classes inside of our lowest layer, which is Foundation. NSString, which is what we use to represent all strings in the system, stores its characters as unicars. It has support for converting to and from all the different encodings that you would expect, and we use it everywhere in our APIs in place of char stars.

On the localization side, we use NSBundle and NSUserDefaults. Perhaps you've heard about the new application packaging model. NSBundle is what allows you to go in and take the pieces apart. You can specify all of your resource files by localization, by language as well, and then NSBundle allows you to retrieve the proper one at runtime based on the user's preferences.

The user's preferences is where NSUserDefaults come in. NSUserDefaults defines, among other things, several different localization defaults which are stored per user. So NSBundle will, for you, look up the correct localization for the current user and load the correct image for you. That's all the time I have to spend on foundation. And I want to move on now to start talking about the kit, because this is really where you're going to see the heart of the infrastructure for your application.

So the kit is where we have the entire infrastructure for drawing and event handling in a Cocoa application. In addition to that infrastructure, we provide all the standard controls ready to use out of the box. As you saw, there's also a sophisticated text engine in there. All the standard dialogues are up there. We tend to call those panels, so there are things like the color panel, save panel, font panel, open panel, all of those things that you saw in TextEdit Lite.

And as I said before, AppKit relies on Foundation for its object structure and the application services layer for its graphics and event handling. So what I'm going to do is walk you through the core classes in the kit, and then we're going to spend a little time talking about the abstractions inside the kit.

[Transcript missing]

One of the subclasses of NS Responder is NS Application. NS Application is concrete, where NS Responder was abstract. So you would never instantiate a plain NS Responder. On the other hand, there is a single NS Application instance in your application. This instance is what is responsible for managing all the communication with the rest of the surrounding system, with the dock, with the Windows Server, and so on.

NS Application also maintains a list of all the Windows inside of your application, and it's responsible for running the app's main event loop, run loop. And during that run loop, what it's going to do is it's going to receive an event from the Windows Server, take it apart, look at it, and say, "Oh, this needs to go to Window X," and hand it off to Window X. Which brings us to the next class, NS Window.

NSWindows reserves screen real estate for you. NSWindows do not themselves draw, but they handle the necessary coordination between other windows and other applications to reserve space for you to draw. When an NSWindow receives an event, it does the work of translating the raw event into the correct responder method and then handing it off to the correct responder to process the event. Well, the events usually come in one of two kinds. They either have a location associated with them, in which case they're going to go to whatever responder corresponds to that location inside the window. Or they're something like a key event, which don't have a particular location.

For that second kind of event, NSWindows maintain a special instance variable called the first responder. The first responder is that item inside the window that gets first crack at key events. And that first responder will change as the application, as the application runs and the user clicks in different text fields and so on.

Okay, the final NS Responder subclass I'm going to talk about is NS View. Like NS Responder, NS View is an abstract class, and it adds the necessary structure for drawing to the screen. It's very simple. You just override the drawRect method on any NS View subclass, and that's where the drawing is done. The views live inside of a hierarchy inside a window, so every view has one superview and potentially many subviews.

Subviews are automatically clipped to their superview's bounds. And NS View is where you're going to find all of the basic support for the UI notions that your users are going to expect, things like drag and drop, context-sensitive menus, tooltips. What you would do if you were interested in one of these subsystems is you'd open up NS View, find the set of methods that pertain to the particular piece that you're interested in, and just override those as directed by the documentation.

So I said NSViews draw. That doesn't mean that you're kind of left without recourse in draw rect and you suddenly find yourself twiddling bits on the screen. We provide a number of objects inside of the kit to help you with your drawing. At the top of the list here we have NSImageRept, String, and AttributedString, all of which know how to draw to a particular location.

NSImage provides compositing support, so that's how you get transparency as well as a number of special effects and compositing images over one another. NSBezierPath gives you abstract drawing in sort of the PostScript sense, where you're drawing lines, circles, rectangles, paths. NSColor and NSFont allow you to set the correct color and font in the current graphics context. And finally, NSCell allows you to encapsulate bits of drawing for reuse in several different locations or by several different views.

We also provide a number of concrete subclasses of NSView ready to use in the kit. NSTextView is one such that we saw in TextEdit Lite. Here I've composited together a number of images that show a number of the different views on the system. So in the frontmost window we have an NSOutlineView being displayed inside an NSTabView. Behind that, you can see NS Ruler View in an NS Text View as well. And at the very back, we see an NS Table View being used inside of Mail.

So now that I've walked you through the basics of NS Responder and NS View, you have the pieces you need to respond to events and to draw. At this point, I'm going to invite my manager, Ali Ozer, up onto the stage, and he's going to show you a simple application that uses those two pieces.

Ali? OK, so my example here, the demo I'm going to show you, is going to approach the AppKit at a much lower level than Mike's example did. Basically, as Becky said, we're just going to show you how to subclass NSView for the purposes of modifying the way it draws and modifying the way it handles events. There's many other things you can do in NSView-- tooltips, drag and drop, and et cetera. We won't go into all that.

But it's going to be equally easy, trust me. So like Mike, we start off with Project Builder. We go ahead and create a new project. This time I'm just going to create a Cocoa application, not a Cocoa document-based application, because we're just creating a one-window, very simple application.

It's going to ask for a project name. Let's call it Dot. Our goal here is to create an application which, when you click somewhere, draws a dot there. And when you click elsewhere, it just moves the dot to wherever you clicked. So that's it. Okay, so there you go. It created a template for us. Now, in this case, the template is really simple. We've got no classes. All we have is the main file that Mike's application also had.

And other than that, there's nothing else. It also gives us an interface builder, a Nib file, like Mike's program did, because all Cocoa applications have a Nib file, at least to represent the menu. And then, of course, it can represent windows and panels and so on. So that's all we get here. Now, again, just so that I don't end up typing lots of code, I have the code written up already. Let's go ahead and say add files.

And we have a class file and a header file. Now, Mike showed you Java, and I'm going to show you Objective-C. At the risk of scaring some of you who might say, what is that? Objective-C is really, it's the original language that Cocoa used to use, and we've added support for Java over the last four years. Objective-C is basically a superset of C, and it's very simple, and you'll see. It's just a little syntactic addition to C that allows you to have a dynamic runtime and message sending that's fairly powerful. So I'm going to add these two files to my project.

We're going to copy them into the project. So there you go. So first I'm going to show you the H file. The H file is where we declare our object and tell the system, tell the compiler what it has. In this case, we're importing, which is the same as including, Cocoa.h, which is basically what everybody includes. And then here, this is Objective-C ways, the way Objective-C declares an object. DotView, which is our view, is a subclass of NSView.

In addition to all the instance variables NSView might have, and all of the functionality NSView has, we add three new instance variables: a variable that declares where our dot appears, a variable that declares the color of our dot, and the radius of our dot. So we have these three properties in our view. Now let's go to the Meet the Class file for DotView.

This indicates that's implementation. We basically first override the initWithFrame method, which is the constructor, if you will, for the NSView class. Here we basically tell the superview, which is tell our superclass, NSView, to create itself. Then we simply initialize the three instance variables that we have. It's a good idea to initialize your instance variables, basic object-oriented programming. So we set the center point to 50, the radius to 5. Now notice that color is another object. It's an NSObject. It's an NSColor.

And Becky mentioned that. That was one of the objects we used for drawing. We basically get one of the prebuilt colors, a red color, and we'll retain it. Basically we hang on to it because it's a property of this view. So that's that. And the other two things we do in this example is draw and handleMouseUp.

The drawRack method, which Becky talked about, is basically where you override to do your custom drawing. In this case, we simply... Get a white color and set, and then draw our bounds. And basiopath with rect basically draws a rectangle. In this case, we just fill the whole bounds of our view with white. And then we go ahead, set the color we have, in this case it's red, and then we create a rectangle, which is equivalent to the size of the dot we want to draw, and then we draw an oval with that shape.

Now, oval, that's square, within a square is circle, so we get a circle, and then we fill it. So these two lines draw white, and then put the dot where the center is. And finally, our mouse-up method. Now, in NSV, you can override methods like mouse-up, key-up, mouse-drag, etc., to handle various events.

In this case, we're just interested in mouse-up. And all we want to do is we take the location of the event, which is in terms of window coordinates, and using this method, we convert it to the current view's coordinates. And this takes care of whether the view is scrolled, whether it's magnified, whatever, and this gives back our center point.

And then we simply call this method, which tells the view that it needs to be refreshed. And the next, whenever it's appropriate, the view will redraw itself, refresh itself. So that's it, as far as the code goes. Now, just like Mike did, we also need to change our interface file. Let me hide project builder here.

Now, I just opened my interface file in interface builder. In Mike's case, he dragged a text view. In our case, we are creating our own view, so we're going to drag this view that says custom view. Basically, here we're saying we're not using a pre-built object, we're using our own object. Let's make it as big as the window here. Let's make the window a little smaller. Now, we also want to tell the system about this view. So we go to the classes tab, we choose an S view, and we say subclass.

And we specify that it's dot view. There are two ways to do this. You can either enter the class name and properties here, or you can actually parse the header file. In this case, I just want to show you how you do this. So, now dot view is known to the interface builder runtime. So we go back in here, we bring up our inspector, and we specify that this view is really a dot view. And as you can see, it changed into a dot view.

I think that's all we really need to do. One more thing we can do is maybe go to the size inspector and make sure that whenever the window resizes, the view resizes. There are a lot of other properties you can set. This is the only one I will do. I will save, and I will hide. Let's go back into project builder. And I think we're ready to go, so I will just say build.

Okay, we're done. So let's run this. Let me hide Project Builder. So here is our application. As you can see, the view is there. The view is white because we told to draw a white background. I hope you can see the difference between the pattern here. And there's our dot at location 5050. So as I click around, the dot basically moves to a new location. The center is updated, the view is told to update, and there you go.

Now if I draw in the corner here or on the side, you see that's clipped to the bounds of the view because automatic, by default, views will clip. In addition, if I put the dot here and I resize my window, you see that the view is resized and the dynamic resizing takes care of everything for you, and the view is constantly redrawn using that drawRack method. So there you go. That's a pretty simple demo of event and drawing handling. So... Great. Thank you.

Okay, so we have one last class to talk about in the core AppKit hierarchy, and that's NS Control. As a subclass of NS Responder, NS Control inherits all the basic infrastructure it needs to handle events, and as a subclass of NS View, it inherits everything it needs to draw.

So control combines those two concepts to add this notion of being triggered or activated by user events. Every control defines what it means for that control to be activated, and at that point, it's going to do something special. It's going to send its action method to its target object.

So target is a very special instance variable for controls. It's usually connected to one of your objects, whatever object you want to respond to the control being activated. And then the action method tells the control what method should be invoked on the target object. So some simple examples of controls are things like buttons or text fields that need to be triggered when the button is clicked or when the text field is edited.

So, as I said, when the control is triggered, the action method is sent to the target object. Very simple. So what happens if the target is null? Well, this does not mean that the action is lost. Instead, this is the control's signal that the action needs to be sent through the responder chain, starting with the first responder of the frontmost window. So some common examples of null-targeted action methods would be things like cut and copy. Other menu commands would be very similar, where you really want whatever happens to be frontmost to respond to the action.

Like NSView, NSControl has a number of subclasses provided inside of the kit, ready to use without modification. I've just listed some here, starting with the very basic ones like Button, Slider, Text Field, ColorWell. NSMatrix and NSScroller are somewhat more sophisticated. Matrix lays out a grid or array of buttons or text fields, whatever you want. NSScroller is what you see at the edge of a scroll view to allow you to scroll through the view's contents. And then we have some very sophisticated controls like NSBrowser, Table View, and Outline View, which allow you to display huge amounts of data.

So I'm going to ask Ali to come back up here and extend dot view a little bit and show us how controls work. Ali? It's usually upper management which changes the future set on you, but in this case, I guess Becky is the slave driver. OK, we'll make a better dot program here. OK, so let's see. We want to do two things to dot view. It has three instance variables, center, radius, and color. We're able to change where it appears by clicking. Now we'd like to change the other two attributes of the dot, its size and its color.

Okay, so let's go back to our dot view. There you go. It's the same dot view we used before. Now, again, I put the code in the oven earlier, and it seems to be ready. I will just copy-paste out of here. Back in here and I will explain what it does. So we want to be able to modify the attributes of dot, the dot, the radius, and the color.

So we have two methods. One of them is called setRadius, one of them is called setColor. Now, the target action methods typically always have one argument, which is the sender. And the sender could be the UI widget, the UI control, which caused that action to be sent. So if a button was clicked, the button is going to be the sender? Exactly.

Now, in the case of radius, typically the control that you're going to use is going to have a floating point value, 17, 89, 42, whatever. So in this case, setRadius gets called, and we set our radius instance variable from the floating point value of the sender. And the sender can be a text field, a slider, or whatever. So we just ask for its floating point value, and that's the radius. And then just like we did earlier, we tell the view that needs to be displayed, because the parameter, some parameter has changed.

Now, color is a little more sophisticated. The sender is going to be something that supplies a color, because we want the color to be changed. Now, Becky talked about NSColorView. That's one view subclass, which is a control, which can provide colors. It's tied to the color panel, and based on changes in the color panel, it supplies colors. And because colors are objects, we first release, that is, deallocate the previous color we had. Then we get the new color, again from the sender, and we retain it. We hang on to it. We use reference counting and co-co, and basically you see that in action here.

And then just like the radius method, we tell the view, set needs display. So that's all the changes we need to do to dot view. And we also have to change the interface, though. So let me hide project builder, bring interface builder back up. Okay, so here's our dot view. Let's clean up the window here. Let's move the dot view up to make room. And let's bring our palette back. As you can see, there are some default elements here, the pre-built objects, as I mentioned earlier. So let's use a slider to indicate the radius.

I'm going to go to the inspector here and change the slider's properties. I'm going to make it go from a minimum of one, default value of five, to a maximum of, say, 300. Now, to set the color, we're going to use a color well, which is this little widget. I'm going to put that here.

This basically is fairly straightforward. It's ready to use. Now, there are two other things we need to do, which is to tell... Tell Interface Builder what the actions that this dot view has. And we do that by going back to our little classes inspector here and... Control clicking to get up a context menu and saying we're going to add actions. That will put us into this mode where we're able to add actions and outlets. So let's add actions. The two we added were set radius.

and Seth Culler. Now, as you can see, DotView now lists Seth Culler and Seth Radius. In addition, it lists facts and print, which are action methods inherited from View. They're always there. Okay, so I think we're done here. We want to build those connections. Pardon? Build the connections. Oh yeah, that's right. We do want to build the connections. Yes.

Okay, so we told DotView what it does. We added our action things. Now we want to form the connections. Now if we didn't do this, it would have been very apparent when I ran the program. To form connections, you Control-click and you drag. So the slider is connected to the DotView, and the message we want to invoke is setRadius. And the ColorView is connected to the DotView, and the action we want to send is setColor. So when this is invoked, it'll send setRadius. When that's invoked, setColor. Pretty straightforward. We'll save here and we'll hide. Let's bring project builder back. Let's build. Okay, it's done. Let's run.

So there's our window. Again, this seems to be a regression, full regression testing indicates it's still working. That's good. Let's test the radius. Oh yeah, look at that. So it says, it sets this radius, says set needs display, yes, and the view system eventually displays it. There you go. Let's also try the color bit.

When you click on that, the color panel pops up, because one way to modify the color here is obviously the color panel. And as you move the color in the color wheel, the color over there is changing. As you can see, again, the action is being sent and everything happens. And I think that's all I want to show. Great. Thanks, Ali. Thank you.

I'm telling you, you've got to watch management. They stop coding and everything goes well. And then they start using terms like regression testing. Okay, so let's move on now from talking about the basic classes inside of the kit to talk about some of the abstractions that we use to make it possible for you to extend the functionality already there.

We already talked about one. We talked about target action. That's an abstraction provided by controls to make it easy for you to customize the behavior when a control, like a button, is triggered. Two others that are very important are notification and delegation. And then finally, I'm going to talk a little bit about some of the data abstractions we provide direct inside the kit.

So notifications is actually a concept that comes from foundation. And we use it to broadcast events throughout an application or to other applications. The basic idea is that when something important happens, you want to notify other people who are interested in it. So the kit defines a number of custom notifications, and I've listed three of them here. Things like NSWindowWillClose, NSApplicationWillTerminate, or NSTextDidBeginEditing. And you can see here the idea is that some major piece inside your application is about to do something important.

The way notifications work is they rendezvous via the Notification Center. So people who are interested, objects that are interested in hearing about these notifications, go to the Notification Center and register themselves as observers. You would say something like, "I'm interested in knowing when a window closes, this is the window I'm interested in, and this is the method that I want triggered." Posters then, when they wish to post, go to the same notification center and say, "Please send the notification NSWindow did close." The relevant object is this window, and then they can also provide a dictionary of additional information if there's any extra information they want carried with the notification.

A very similar concept is delegation. Delegation allows one object to act on behalf of another. So several of the different Kit classes support delegates. The idea behind this is to allow you, the developers, to avoid subclassing just because you want to provide a small amount of customization. We do not think it is appropriate to subclass NSWindow just because you want to detect when the window is closed and provide a little custom behavior at that point. By not subclassing, you can do this in a much lighter weight way. This also allows several objects to share a single delegate, saving on memory size.

Unlike notifications which are strictly passive, the delegate object is allowed to affect the process as it takes place. So, whereas we have the notifications NSWindowWillClose and NSWindowDidClose, the matching delegate method is WindowShouldClose. So, when the window goes to close, it will send the delegate the method WindowShouldClose. At that point, the delegate can do whatever it wants, and ultimately will return either "yes" meaning "allow the window to go through its closing procedure" or "no" the window must remain on screen.

So to implement a delegate, you need to choose an object on your side to be the delegate, and you need to choose the kit object you wish to delegate from. Look up the class for the kit object. You will find a list of delegate methods available to you. Read the documentation and figure out which of those methods are of interest to you, and override only those. Once you're done with all of that, just call kit object set delegate, passing your object's reference.

Okay. Now, like I said, delegation and notification are very similar concepts. They're ways that your objects get informed about important things happening in the user interface. But there are some very important differences. Notification observers are strictly passive. They are merely being informed that a change is taking place. Delegates, on the other hand, are active and permitted to interfere with the process and even prevent the change from taking place.

As a side effect of this, there will only ever be one delegate for a given kit object. On the other hand, there are as many observers as care to register with the Notification Center. And you'll see this difference in the naming. As I said, notifications usually have the word "will" or "did" in the name to show that a change is about to or has just completed taking place. Delegate methods tend to be named "should" and have a return value that the delegate can use to prevent or change the behavior of the change that was going to take place.

That's all I have on notifications and delegation. Now I'm going to talk a little bit about the data abstractions inside the kit. By and large, the kit is centered around drawing and event handling. So most of the classes in there are subclasses of NSView, or NSResponder, as I said. However, we do provide a few pure data objects, and those surround these data abstractions. I've listed a few of them here. NSDocument is the central-most class in the document architecture. It's what Mike used to represent that text document in memory.

NSImage and NSImageRep are used to represent images and the multiple representations that they may have. NSFont is an abstract representation of a font. NSAttributedString allows you to store attributes over a string. So beyond just the characters, you can mark particular regions as having particular attributes, like italics, like a particular font. And then finally, NSColor, which we saw in dot view, represents a color.

So, when you look at a Cocoa application and it all comes together, this is what you're going to see. There is a single NS application instance, which handles all the communication to the rest of the system as a whole. It also maintains the list of windows inside of the application.

NS applications have a delegate, which you can choose to implement. NS windows have delegates, again, which you can connect and choose to implement. And then those objects are going to talk down to whatever data objects you use to represent your internal data, the things that are peculiar to your application.

If we take a close-up look on that window, we can see that inside the window there are a number of views being displayed, one of which might be a custom NS view, like that dot view that we used. You might also have a number of concrete subclasses of NS control that are kit objects that you're using directly from the box. All of those are talking down to the layer below it, which I've represented here simply as a window delegate. It could, of course, be several different objects of several different classes. And then off the bottom, that talks down to your data model underneath.

All right, that's all I have to tell you today about the kit and about Foundation. But I am going to give you a couple pointers for where to go for more information. The first of these is documentation. You would be just amazed at how much documentation is on your DP4 CD. You can find the release notes there. There's overview documentation, which goes through everything I've talked about here, as well as a number of other different concepts. There are programming topics that are covered in-depth in particular documentation files.

The class references are all online. They give a complete list of all of the methods on the different classes and what the methods are used for. And then finally, there's a fair bit of example code, including the TextEdit application, which I mentioned earlier. To find the documentation, look in System Developer Documentation Cocoa. All of that is also available on the web at developer.apple.com/techpubs. And the example code can be found in System Developer Examples App Kit.

All right, finally, where do you go from here? These are some sessions that I think are worth taking a look at. Cocoa In-Depth is the follow-on session to this one. As I mentioned, they're going to be talking about the text subsystem there, as well as the document architecture, and a number of other more complicated concepts that we did not have time to discuss here.

Cocoa Update is where we're going to talk about what's changed since we met here last year. Just a word of warning, that talk does assume that you are already familiar with Cocoa as it appeared in DP1 last year, which does not mean you should not go just because you're not familiar with Cocoa. Just a warning that you might find yourself in a little deep.

The next line is a mistake. You're not interested in Core Foundation Advanced. You're interested in Core Foundation Basics. That's 124 in Hall A1 tomorrow morning at 10, I believe. And that's where you can find out about property lists in greater detail. And then again, Project Builder and especially Interfacer Builder are definitely worth taking a look at if you're not familiar with them and how they are used. And I've listed their two introductory sessions here.

Finally, I'm going to invite David Wright back up on stage. David? Ah, there we go. And he's going to take us through the Q&A as well, so if you want to start getting to the microphones in the aisles, that'd be great. David Wright: Great. Thanks, Becky. Thanks, you guys, for the demos. Let's give it up for him.