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: wwdc2003-400
$eventId
ID of event: wwdc2003
$eventContentId
ID of session without event part: 400
$eventShortId
Shortened ID of event: wwdc03
$year
Year of session: 2003
$extension
Extension of original filename: mov
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: ...

WWDC03 • Session 400

Introduction to Developing Applications with Cocoa

Application Frameworks • 56:23

Cocoa provides powerful object-oriented APIs for creating full-featured, next-generation desktop applications on Mac OS X. This session provides an introduction to Cocoa, and through demos shows how you can use the power of Cocoa to easily create Mac OS X applications that take advantage of existing C or C++ code.

Speakers: Matt Formica, Tina Huang

Unlisted on Apple Developer site

Transcript

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

Thank you, thank you. It's been a long day. How are you guys doing? Everybody okay? Excellent. So today's going to be a really great session for those of you who are either new to the platform or have been here a long time and want to see what's happening on the Cocoa side.

We've got two really great people. We have Matthew Formica, who is a developer technical support engineer, and we have Tina Huang, who is an application framework engineer, and they're both going to talk to you about why you should be using Cocoa and how cool you can do things with it. So let's start with Matthew.

Thank you, Jason. We are going to get right into the material here today. What we're going to talk about today is what Cocoa is. Some of you may be here, as Jason said, for the first time. You're not really familiar with Cocoa, although you may have already heard about it. We're also going to talk about what some of the benefits of Cocoa are for you as a developer, and how you can use it in a variety of application settings, and we'll have some demos along the way.

So let's dive right in. What is Cocoa? Well, what we like to say is that Cocoa is a powerful, full-featured, easy-to-use, object-oriented framework for Mac OS X development. And that's kind of a mouthful, but basically it means more rapid productivity for you as a developer, thanks to its object-oriented underpinnings. And we believe at Apple that it is, in fact, the fastest way to full-featured applications on Mac OS X.

This is an architecture diagram illustrating some of the layers that make up Mac OS X. At the bottom is Darwin, the Unix layer. On top of that sits some graphics technologies, Quartz, OpenGL, and QuickTime, and then a layer of frameworks. These are the layers that your applications will typically write to, such things as Java, Carbon, and Cocoa. And what we're going to focus in on today is Cocoa.

We talk about Cocoa as this one monolithic thing, but when we drill down a bit, we see that there are really two core frameworks that make it up, Foundation and AppKit. The way this works is like so. Foundation is where the non-graphical user interface components of Cocoa reside. Such things as strings and networking, scripting, and file system calls reside here.

If you're writing an application that doesn't use a user interface, you could just link against Foundation, and you'd be set. However, if you do want to use a graphical user interface, you'll want to add in AppKit. AppKit contains classes for controls and windows and other things that do use a user interface as part of the application.

We can actually go beyond this. Besides these two core object-oriented frameworks, Foundation and AppKit, there are a variety of other pieces of the system that work together to make the Cocoa experience what it is. These include things like our development tools. Project Builder and our newly introduced Xcode, along with Interface Builder and the performance tools on the system, all have features carefully designed for Cocoa development. On top of this, we have powerful and dynamic languages that provide the support to make Cocoa possible. Objective C and Java.

All of these work together to help you write code faster. The framework APIs are mature, they've been around for a long time, and they've been designed from the ground up with an object-oriented approach in mind. Besides this, they leverage Objective-C and the dynamic runtime that it provides in a few different ways.

Objective-C and Cocoa code are weakly typed, and so they allow you to reuse more code because the code you write will tend to be more generic right out of the box. In addition, there isn't a need for such complexities as templates, often a source of confusion in C++.

Objective-C and the dynamic runtime also enable you to create more effective shared frameworks. You don't have application binary interface issues like you might with other languages, and you can extend base classes without breaking applications that depend on them. And thirdly, we have this concept of categories. This is a language feature which is very powerful. You can add methods to existing classes without having the source code do them.

So, for example, if you write, say, a program that's a million lines of code, and you use our Unicode-compliant string class, NSString, throughout that code, and then discover there's one more method you wish all strings in your program could take advantage of, you don't have to go and replace your use of NSString with a subclass. Simply add a category to NSString and add that method. Very powerful.

And all of this adds up to help you be faster to market with your products. You can spend your time developing your application's unique features instead of reinventing the wheel. and enables you to write less code. Cocoa keeps simple things simple and makes complex things possible. It raises the baseline for the code that you write, so you're writing your application's unique portion. In addition, your application can automatically get new features over time without recompiling or reshipping. Thanks to the dynamic nature of Objective-C and the Cocoa runtime, your application can take advantage of features as soon as they appear in the operating system. They just automatically show up.

And so we've been talking a lot about the languages that are used up to this point, so I want to focus in on that just a bit. There are really two languages that are supported for Cocoa development: Objective-C and Java. I'm sure you all know what Java is, so I'll focus on Objective-C here.

It's actually a language that was invented in the '80s and is today a standard part of the Free Software Foundation's GCC distribution. And it's a very dynamic language, and along with Java, provides the support that Cocoa needs. In addition, if you're writing in Cocoa, you can plug in your Carbon C or C++ code right into these languages. Or if you have Unix code, they integrate in as well.

So that still leaves the question open, which language should you use? And really the answer is, use the language that fits your needs. You may find that you have existing Java code or libraries that you want to take advantage of, or you may have code out in the community that you want to take advantage of. If so, you may find that writing your application in Java using the Cocoa APIs is the best road for you.

On the other hand, most developers find that the faster runtime performance and lower memory overhead of Objective-C make it the language of choice. We'll focus in on Objective-C today. With that, I'd like to turn things over to my associate, Tina, to talk a little bit about some of the details of how you actually go about programming in Cocoa.

Thank you very much, Matt. Once again, my name is Tina Huang, and I am one of the Cocoa Frameworks engineers. So basically what I'll be talking to you about in this section is three things. First, we're going to cover some of the fundamentals of Objective-C syntax. Then we're going to go over some of the various Cocoa design patterns. And finally, we're going to talk about some of the various developer tools we have for you on the system.

So in order to illustrate some of these concepts, we're going to take a look at this simple to-do list example. And in particular, we're going to focus on adding a preferences pane to this to-do list. And for those of you interested, later on in the talk, Matt's going to come back on stage and actually show you how you can integrate this preferences pane into a Carbon application. So let's just jump right in and take a look at Objective-C syntax.

Here's a copy of valid Objective-C code. Here is a function that converts from Celsius to Fahrenheit, and it probably looks very familiar to a lot of you. Well, that is because Objective-C is a strict superset of ANSI C. So all your old ANSI C code from your old apps is still valid Objective-C code. So you don't always have to look at Objective-C for your answers.

However, Objective-C does provide a few additions on top of ANSI C. The first is we wanted Objective-C to have an object-oriented layer on top of strict C. So this included having new syntax to define new types of classes and to actually deal with those different objects. And most importantly, we wanted the ability to send messages to these objects.

In Objective-C, one of the very unique things about it is we pass messages to objects rather than invoke methods. And this means that the actual code that's executed is determined at runtime. So in order to do this, we needed new syntax to send messages, and we needed runtime support for these messages, and finally, we needed various data types for these messages. So let's just jump right in and look at some messaging syntax.

So for those of you familiar with any other object-oriented language like Java or C++, you might be used to a method called looking something like this. So here you're sending a do-something method to my object. Well, in Objective-C, each message begins and ends with a set of square brackets. To the right of the opening bracket, you have the receiving object, and to the right of that, you'll see the do-something message. So here is a complete Objective-C message.

Now you can also have a message that takes any number of arguments. So in a traditional object-oriented language, you would have something like this, which is an ordered list of arguments. Now in Objective-C, we have something new that we refer to as name parameters. So it looks something like this.

You begin, once again, with your receiving object, and then to the right of that, we're going to have the do with this colon, end this colon message. The colons are part of the message name. And to the right of that, you will see the various parameters that you pass in. And you have one parameter to the right of each colon.

So this is how you pass messages in Objective-C. Now, some of you may wonder, why would we want to do this name parameters? Well, in short, this generally just improves the readability of your code. In this case, it's pretty obvious, the two objects that you're trying to send.

But you can imagine a case where you have an initializer that you're taking in 10 different arguments. Now, granted, the Java method of just having 10 arguments in a list might seem shorter. However, you can imagine that you might start confusing which argument goes where, and having the name parameters can actually be very useful.

So let's take a look once again at these messages, but let's focus particularly on the parts in orange. So the part of the message independent of the parameters is referred to as the selector of the message. And you can actually programmatically access this part of the message using what we call the atSelector syntax.

Now you may wonder, why might I want this? Well, this allows you to access a message independent of the receiving object's type. And what makes this really powerful is the fact that at runtime and compile time, the type of the receiving object does not necessarily have to be known.

And this is because Objective-C is a dynamically typed language. The type of the object is actually determined at runtime. And so we have this generic ID object that can represent any object type. And you're actually allowed to query the object at runtime and ask it what class it is and what methods are available to it. And so you can actually use this message, the response to selector message, in order to find out first if an object does actually accept this message, and then if it does, send it the message.

So now that we've looked at some of the specifics of Objective-C syntax, let's step back a second and take a look at some generic Cocoa design patterns. And the first one that we want to talk about right now is memory management. So Cocoa uses something called reference counting.

Basically, when you retain an object, this increments your reference count. When you release the object, you decrement the count. And we have something called auto-releasing that decrements it at some later point. And an object is freed whenever the reference count drops to zero. And so there are a few rules to the memory management contract.

The first being, only creation methods, and this is init, copy, and new, will actually return retained objects. And in all other cases, the receiver is responsible for retaining the object when it first gets it, and releasing it when it's done. and once again, an object is deallocated once the retain count drops to, there are no remaining references, and the retain count drops to zero.

So now we're going to look at another Cocoa-specific design pattern. And this is actually going to deal with communicating with the interface. So you can imagine that in your interface, you have some element in your UI, and you want it to basically effect change on your application. So first, when we're talking about that, we use something called target action.

And so you can imagine you have a button in your application, and the user clicks this button. So what happens? Well, essentially, this sends some sort of button-clicked action message to whatever your controlling object in your application is. And we refer to this controlling object as the outlet of the action.

Now, in Converse, what if you have your application and you want it to actually drive the UI and update changes in your interface? Well, to do this, we use something referred to as outlets. So here we have the same controlling object as before in your application, but you also have some sort of text field in your interface.

And essentially, you want your controlling object to pass some sort of message to this text field and say, set the text field's value to be whatever the string is. And in order to do this, you basically need a handle from your controlling object that ties it to the text field. And so in order to do this, you set the text field as a controlling object's outlet.

So for many of you, this whole communication with the interface may seem very reminiscent of something, a general software design pattern called Model-View-Controller. So for those of you who have never heard of this before, Model View Controller essentially divides application into three layers. At the very bottom, you have the model, which is what stores and manipulates all your user data. At the very top of it, you would have the view, which is everything the user sees and interacts with. And somewhere in the middle is actually this controller, which is the glue that ties the model and the view together.

And so to tie this back with some of the earlier design patterns of target action and outlets, let's take a look once again at our button. So the button is part of the view, and when the button is clicked, it sends an action message, but that object that it would send the message to is referred to as the controlling object. So that is your controller.

And this controller, in turn, would send the message to the model and tell it to update. So in this case, it would tell the model, well, create a new folder. And this is really important because now you have the user interface isolated from the view. And so you can make changes to your interface and not have to modify-- user interface and not have to modify your model in return, and vice versa.

And most of your application-specific code is now isolated in the controller object. And you can imagine the reverse of this is if something changes in the model, and that would cause a message to be sent to your controlling object, and then that would cause the UI to update through the use of an outlet.

And in order to do this, we actually have this really neat developer tool called Interface Builder. Interface Builder essentially allows you to have this easy, quick, drag-and-drop graphical manipulation of your UI. And so it's very easy to develop your user interface to your application. Unlike most other interface tools that essentially just spew out some source code to represent your view, what Interface Builder does is actually very unique. It archives live objects and also archives their connections. And these connections are the target action connections and the outlet connections that we just referred to.

And finally, it's completely integrated with Cocoa. From the day that Cocoa was built, essentially we had Interface Builder, and the two of them are built up together. So it's not like we have this old developer tool and we have this new builder that just kind of does the same thing that writes more code. It's really there to help you and make coding easier for you.

So in order to show you some of, we want to now show you some of the coolness of Interface Builder. So, Interface Builder creates and archives your files in this nib format. And so, here's my project with my to-do list, and I'm going to take a look at that file.

So here is basically a view of what is in your nib file. And so you have your main window and various other properties of your nib that we'll go into in a little bit. Up here you'll see that there is your-- a palette of controls that you have available to you. And finally, we have the Inspector window, which allows you to see the different properties of your controls.

And so if you're trying to build something like this Preferences pane, you can start with, like, over here we have a text view, and you can just drag it over here. And notice that these blue grid lines drop up. Well, these are basically guidelines to help you meet the Aqua specifications. So even if you have no idea how to design a view that meets Apple's criteria, all you can do is follow these lines and you can make an app that looks like all other Macintosh apps.

And so now we can do the same by dragging out a checkbox. And over here in the Inspector window, you can see there's a title, and we can You can set the title to be something like Show Completed Items. And you can drag it out to be whatever size you want.

I can just drag out some radio buttons. And you can see here that you can change the number of rows. And adjust it once again. Notice how easy the Aqua guidelines make it to adjust the spacing. And if you click on each of the items, you can set the values. And so we'll make that one red. And we can make that one blue.

will make this black. And finally, we'll add a button to the bottom. And we'll tell this one to clear the to-do list. And once again, notice how easy it is to adjust your UI. And so, since Interface Builder actually deals with live objects, you can do something that we refer to from the File menu. You can choose Test Interface. And this actually lets you play with the interface as it would really work. So you can see how the checkboxes check and the radio buttons click, and click on various buttons.

So now that we have our UI, we need to control our object. And Interface Builder actually allows you to do that. So in our NibFile viewer here, we have a tab that shows-- a tab labeled Classes. And this essentially has all the objects that that NibFile knows about.

So in this case, it's all of the AppKit objects and any objects that you specifically tell the Nib about. We're going to subclass NSObject because that's the most basic of the objects. And when you hit Enter, it gives you a subclass, and we can name it PrefsController. And here's a PrefsController object.

And I, that shouldn't already be created, but essentially here you have We're going to call it MyObject here since I've apparently messed up my demo here and have a prefsctl object instantiated. So let's say you have an object called MyObject. And in the Inspector window, you can see that you can create outlets and actions right here in Interface Builder. So let's add some outlets. So we want an outlet to represent the color button. And we can add an outlet for the Show Completed button. And finally, we can add an outlet for the title field.

You can do the same for Actions. So we'll have an action to clear the list. And we'll have an action to set the color. And finally, an action to set whether or not you want to show completed items. So once you have that, then you can create the files, have Interface Builder create the outlines for-- outline template for these files. So we look at my object, and in the Classes menu, you can tell it to create files for my object. And here it'll tell you-- you can choose to create both the header and the implementation file, and tell it, put it in my project.

Now, if you go back to Project Builder and look at it, you'll see that it's created these two files for you. So, if you take a look at them, Notice that no behavioral source code is generated for you. And the advantage of this is really that once you create your view and your model, you can actually just change the positionings of your view and change the way it behaves and not have to change your code necessarily. And the same happens for your header files.

So let's go back to Interface Builder. And so each Nib file has to be loaded by some object of a particular class. And by default, it's NSApplication. But you can actually set this in Interface Builder through the files owner. So every Nib file has a files owner. And you can actually, in the inspector, you can tell it, show me the custom class. And as you can see, this is NS application. Well, in this case, we're going to set it to be myObject. And here it gives you a warning saying that you're changing the files owner from application, and that's OK.

Now you have a way to essentially hook up your controller to your view. So the way that that's done, and once again, remember the slide with the target in action, you basically want to connect your controller to the items, the controls in your UI. And so, for instance, let's take a look at this clear to-do list button, and you essentially want that button to send an action to the controller object. So you would hit Control and drag from that button to the controller object, and you could say, "Clear list. That's the action I want to happen." And you could say, "Connect." And you can do the same for the various buttons.

[Transcript missing]

and Tyler to set the show completed. Now again, the converse of that is what happens when you want your controller object to have access to your UI elements. Well, you want your controller object to be able to send messages to controls in your UI. So you control drag in that direction. So you control drag from the controlling object to an element, a control in your UI, and you can say, that is my setCompletedButton, so set that outlet. And you can do the same for The Color Button, and we'll want to set the title field.

And that's basically how easy it is to hook up from your UI to your control object. So, for sake of time, we're actually going to jump to We've polished up the UI for you a bit, and we have actual controller code implemented, because obviously when that action message gets sent, something has to happen. And we're going to build and run that for you.

Hi, this. And so here you can see, if I go to File, the demo, and open up the preferences, let's first create a few items.

[Transcript missing]

and I are going to show you how to create a full-featured, next-generation desktop application on Mac OS X. So there's one more thing we want to do here, and that is we want to be able to type in the to-do list title and actually have it update in the to-do list.

Well, using that target action pattern, we can have some sort of apply button that will tell the title list to be set, but there's a better way to do that, because we want to have an actual live update from... The Preferences Pane to the Actual To-Do List. And let's actually go back to slides here.

In order to do this, we use something referred to as delegation. And this essentially allows an object to appoint another object to be its delegate. So what is delegation? Well, let's think of it in a non-coding fashion. We have my boss, and he's about to go on vacation. So he essentially appoints Matt to be-- he says, Matt, I want you to be my delegate. So all messages that would go to my boss will now go to Matt.

And so now I'm like, I want to go on vacation. And normally I would say, hey-- I'd ask my boss, can I go on vacation? But obviously he's not there. So that message now gets forwarded to his delegate, who in this case is Matt. And Matt says, sure, Tina, go on vacation, because he's a good buddy of mine. So this is delegation.

So in Cocoa, we actually have two basic behaviors that Delicate can perform. The first is, the delegate can actually modify the default behavior of the object. And the second is, it can just be a receiver of notifications. So whenever an object performs a certain event, the delegate can just be notified that this event has occurred.

And so there are several classes in AppKit that have a delegate outlet. And when you set this delegate outlet, essentially the delegate will be asked, hey, is it OK if I do this particular action? Or the delegate could just be notified that something has happened. And so, for instance, if you have some sort of text field in this case, the delegate may be asked questions like, is this a valid value for my text field? And, for instance, if you want the text field to only accept numeric values, you can adjust the behavior accordingly. And in another instance, you can just want to know, well, the text is about to change.

And so the delegate can just be notified that the text is about to change. to be changed. And so essentially what this allows is you can customize an object without having to subclass it. So let's take a look at how this works. So we're going to go back to our Nib file.

And if you look at the text view, Notice that it has an outlet called its delegate outlet. And so you can control drag from the text view, to the files owner, which is the prefs controller, and say, "Make this my delegate." and Yudal get set. And so let's take a look at the code that was necessary, that is necessary to make this change.

So let's take a look at the press controller. And what you want to see here is this TextedChangeDelegate method. And essentially this is called whenever the text changes. And so here we're going to tell the title field to set its font and set its string value, and then update the window. And so now if we build and run this.

Too many windows here. So now if you open the Prefs pane. When you change, type the text, so I could say this is, you know, like, my shopping list or something, notice that it live updates on your to-do list. And so delegation is a very powerful tool. and I will be talking about the basic design pattern that Cocoa allows you to do.

So there's one more thing. We want to be able to set the font of this to-do list. And in order to do this, we need something that's slightly different from this general target action design pattern that we've shown you up to this point. And the main reason for this is, well, a font panel that you've probably seen before on OS X, it can affect any number of views. And so it's targets essentially determined on the fly. And so let's go back to slides here.

And so in order to do this, we use something called the responder chain. And this allows us to determine what our target is at any given moment. And so the responders chain is essentially an ordered list of objects that responds to user events or events in general. And this means that the target can be determined at runtime.

In particular, the first object in this responder chain is referred to as the first responder, and that's the actual object that will receive the event. And so the Responder chain is used in various places. For example, cut, copy, and paste. You click on one text view, and you say, copy this text. And then you click on some other text view somewhere else, and you say, paste.

And so First Responder allows us to track what your main window is and determine that new view is where I want the text to be pasted. Also for menu item validation, you can validate menu items depending on where you're clicking. and once again, you can use this for things such as font panel and color panel. And so let's show you how that works.

So essentially, right now we're going to look at this other nib file, which I haven't shown you up to this point, but this essentially is the main window of your to-do list application. Let's clean out some of these windows. So this is the main view of your application. And in here, though, you'll notice that there's this main menu. And this is essentially the menu bar that is associated with the application.

And so in your controls palette, you have a bunch of menus that you can add to it. And in this case, we're going to add a fonts menu. And notice you can have a whole array of things. You can show the font panel, bold, underlining, things like that. So let's save this.

[Transcript missing]

Notice here that we now have a Fonts menu in our To-Do List application. And you can just say Show Fonts, and the Font panel comes up. And so let's take a look at our preferences. And so here, I want to emphasize that's my list, so I can make the font really big. It's probably a little bit too big.

Hello, everyone. I'm Tina Huang, and I'm the C++ developer at Cocoa. and I will just make it all 36-point font. Essentially what you see here is that whatever view I have currently selected, You can now have the font panel affect that particular view, and that's because this text field here is the first responder.

Can we go back to slides, please? And so that's essentially Cocoa in a nutshell. You know, we don't expect you to be full-fledged Cocoa programmers by any means at this point, but hopefully you have a general understanding of, you know, the various powers that Cocoa provides, and you'll understand enough about Cocoa syntax to hopefully participate in some of the other talks that we have available for you later this week in the Cocoa track and learn more about Cocoa. So I'm now going to pass this back to Matt to talk to you about how to integrate this preferences pane in a Carbon context. Thanks, Tina.

So this next part is actually one of my favorite parts about Cocoa. It's something I think is really cool. And that's how you can integrate Cocoa with other technologies. You can certainly use Cocoa to build full-featured applications with Mac OS X. But a relatively newer development is the ability to integrate Cocoa with Carbon and even Unix code. You can mix Cocoa code right in with your existing C and C++ code, and we're going to show you how to do that today and why you would want to do it, and then walk you through a demo.

So why mix Carbon and Cocoa? Well, there are three basic reasons. First of all, you may have existing code that you want to leverage. This is typically the most common reason for integrating Carbon and Cocoa. There's an app that exists in Carbon, and you want to add some functionality using Cocoa.

The second reason why you might want to do this is if you're writing a common service that perhaps applications written with Carbon or Cocoa could take advantage of. For example, the address book framework on Mac OS X actually vends APIs in both C and Objective-C for both of these frameworks. And finally, there may be various pieces of alternative functionality that you find easiest to access through one framework or the other, and so you want to integrate those in one application.

So what does this involve? Well, it basically involves just adding the code, whether it's Carbon or Cocoa, to the same source file. Go ahead and include Carbon.h or Cocoa.h, or both. The other thing you'll want to do if you're including Objective-C code in your existing C or C++ source files is change the file extension to .m to indicate that Objective-C code will be included. If you're also including C++ in the same code, you'll want to change the extension to .mm to indicate that our other compiler, the Objective C++ compiler, should be used. This technology allows all languages to coexist in the same source file and be compiled.

If you have source files that you expect to be compiled on other platforms where perhaps Objective-C doesn't exist, and yet you want the code to just kind of go through smoothly, you can use the #ifdef objc syntax. And that basically says, if this is defined, then we're compiling using a compiler that understands Objective-C. and you can also force the right compiler to be used on files without having to change the file extension if you choose.

So besides compiler support and source code support, the operating system has support for mixing Carbon in Cocoa as well. The OS itself provides what we call toll-free bridging of common data types between foundation in Cocoa and the core foundation framework. Such data types as CFString and NSString can be simply cast one to the other. In fact, they're the same object.

And there are actually two main levels of integration between Carbon and Cocoa that we support. Prior to Mac OS X version 10.2, we supported non-GUI integration. So you could have, for example, Carbon or Cocoa code that dealt with the file system, and then have the interface be designed using the other set of APIs. We changed this in Mac OS X version 10.2.

We now support mixing the graphical user interface on a per-window basis, which means you can have a Carbon window in a Cocoa application, or a Cocoa window in a Carbon application. And the one thing to keep in mind is that you'll want to call this one function, NSApplicationLoad, to initialize Cocoa if you're using Cocoa within a Carbon application.

So we've got a kind of nifty little demo here to show you guys. You may be familiar with the Glypha 3 code base. It's been around since 1988, 15 years. It was written by John Calhoun of Glider fame for the Macintosh. And today, it's fully carbonized and lives on sourceforge.net, where the source can be downloaded.

So let's show you this game. If we can switch to the demo machine. Tina's going to create-- start a new game. It's basically a joust clone. And the source code is available. You basically sail around on your bird, trying to knock sphinxes out of the air in, I guess, some sort of an Egyptian pyramid. And she's going to try and get on the high score list here.

This code was Pascal black and white back in the day, and then it was retrofitted to C and color, and various technologies were added over the years. It was finally carbonized. I remember playing this on my Performa 600, 33 megahertz, back in the day. So she's dive-bombing into the lava.

There's actually a mummy hand on the left-hand side that comes up and grabs you if you're not effective. So here's the high-score dialogue, and actually, given the history of this code base and its Pascal string, ANSI string usage, all we can enter is English at this point. We're going to retrofit this to be able to support more languages. We could do this in Carbon. We're going to do it in Cocoa.

We could imagine we would want to add other technologies to this using Cocoa down the road. So she enters her name. We get the high-score list. She's number one. And now, let's take a look at some of the architectural changes we're going to make to this. So we could go back to slides, please.

There are two things we're going to change. We're going to add a preference panel using Cocoa, similar to what Tina illustrated earlier. And then we're also going to change the high score name entry dialog to be Cocoa. So before the integration, what does this code look like? It's basically six source files. It's straight C. It includes a kind of basic sprite engine and sound engine. It was something that John Calhoun actually used to learn how to program through the years as he was working on Glider for the Mac.

It includes high score lists and other preference code. It saves all these out manually using its own data structure, which it then stores out. We're going to change that a little bit. We're going to go more towards the model-view-controller approach that Tina illustrated and access some of this through a preferences model instead of directly to the struct.

And we've taken the liberty of making some Carbon modifications to the code before stepping in with Cocoa. Basically, what we've done is replaced the Pascal strings with CFStrings to finally support Unicode and other languages. This enables easy data transfer to NSStrings. As I mentioned earlier, we can simply cast the CFString to an NSString or vice versa.

So let's go look at the other Cocoa changes we've made to this code. The first thing to notice looking at the files here is that we've changed the extension on main from main.c to main.m. This indicates that we'll be including Objective-C source in this file. And if we open it up, we can look at the code that actually handles preferences.

When we load preferences, we pound ifdef obc, this code, just in case we were to compile it on another platform. I'm not quite sure why we'd want to do that here, but it illustrates the point. And what we can see is that we're calling NSApplicationLoad to initialize Cocoa. And finally, we create a new prefs model object and initialize it with a preferences data structure that Glypha 3 natively uses.

So that loads in preferences when the game starts up. Then when the preferences menu item is chosen in the game, we need to actually go and create this new Cocoa preferences panel. Once again, we carefully conditionalize our code, and then what we call is NSBundle's LoadNibNamed method. And this actually takes a nib name as its parameter and basically loads up our preference panel, which it then displays on the screen. Let's take a look at that preferences panel now.

Here it is. It should look very similar to what Tina showed earlier. And we've made just a couple of changes. You'll notice a Show Fonts button here. And what that's for is, basically, we can't add a fonts menu to a Carbon resource manager-based menu bar. So we've added a fonts button here to actually show that font panel.

Other than that, it's basically the same. From a Carbon perspective, we don't have to know anything about how checkboxes and radio buttons are implemented. All we need to do is write the code that gets run when these controls are triggered. Speaking of which, let's go look at the setSound method now. Here we go.

This code is fairly straightforward. It basically gets the state of the checkbox, and if it's on, it turns on the sound. If it's off, it turns off the sound. And then it synchronizes the model. Pretty simple. Now let's take a look at the other nib in this game that we've added, which is our new high score entry dialog. And it looks very similar to the Carbon one we showed before, as it should. So let's take a look at the code that loads this nib.

Once again, we allocate a new controller object and then call loadNibNamed to actually load this high-score entry dialog. So those are the changes we've made. Let's run the app now and see how this new retrofitted version of Glypho3 works. So we actually have a preferences panel now, which we can pull up.

So this is a Cocoa window running in a Carbon application that's been around for 15 years. We can go and change the name of the high score list. We can pick a different font while we're at it. Let's pick something a little more Egyptian, like Papyrus or something.

Make it a little bigger, maybe. And sound is on, so okay, good. So let's close those windows, and actually Tina will go and play a new game again. If you download this from SourceForge, play it all day, I was pretty good at one time. She's made it to the high score list at this point. I think she's just going to take her lucky now.

died a gruesome death, and now she can enter her name, but we're not limited to English anymore. We can actually have Tina go enter her name in Chinese. thanks to the power of end-to-end Unicode support through NSString and CFString, her name is displayed now in Chinese. Let's go back to slides.

So what have we learned today? Well, we've learned that thanks to the object-oriented and very dynamic frameworks in Cocoa, your development can be faster. We've also learned that the Cocoa fundamentals really aren't that hard to learn, and Objective-C is really not that bad. And finally, we've learned that you can integrate Cocoa into your existing applications or build whole new applications using Cocoa. At this point, I'll turn things back over to Jason for wrap-up. Thank you, Matt. Thank you, Tina.

[Transcript missing]