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

WWDC06 • Session 129

Cocoa for Carbon Developers

Application Technologies • 59:02

Cocoa provides the fastest way to full-featured, extensible, and maintainable applications on Mac OS X and, for many Carbon developers, Cocoa also provides the easiest way to add new technologies. Learn the ins and outs of what it takes to integrate Objective-C frameworks and a Cocoa user interface into your existing Carbon application. You'll also hear development strategies and advice from those who have already made the transition to Cocoa from Carbon.

Speakers: Deric Horn, Scott Thompson

Unlisted on Apple Developer site

Transcript

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

Like the voice of God just said, I'm Deric Horn, the Application Frameworks Evangelist, and what that really means to you is if you ever run into blocking issues or need help escalating a problem, you can always email me. You'll see my email at the end of the presentation. It's just deric at apple.com. But I'm glad you're all here. This is really important stuff that you really need to know, and it's not that hard to learn. So I think that you're going to find that with a small investment, you'll get a big return.

So before I get started, I'd like to ask a couple questions, though. I'd like to know how many of you are currently using Xcode for your primary development environment? Excellent. Everyone's universal. And how many of you are currently writing Cocoa Objective-C code? All right, a couple. And how many of you are planning on writing Cocoa and Objective-C code in the next six months? Excellent.

Well, you guys came to the right place. So I'm a lot like you guys. I've got a long history and a big investment in Carbon. But you'll see that Cocoa has some incredibly enticing features. So everything I talk about today is going to be from the Carbon perspective, perspective of a Carbon developer.

So this is quite a broad subject to cover in one hour, so I'm going to take what I kind of call a shotgun approach. I'm going to cover a little bit about a broad area. And I'm going to have to make some assumptions. I'm going to have to assume that you're aware of object-oriented design and I'm going to have to assume that you drank as much coffee as me, because I'm going to have to talk fast to get through all this stuff. We'll start by going over an overview of Cocoa, some of the Cocoa design philosophy, how to get things done in Cocoa. Then we'll talk a little bit about how to get started with Objective-C.

What you need to know to get started in Cocoa. Some tips and tricks that I've picked up along the way that will hopefully save you time and effort. And then I'm going to talk about migration strategies. So given the current state of your application, how do you bring that forward into adopting some of these killer new Mac OS X technologies that are Objective-C based? We put together about five different demos for this. They're all what I call, they all make use of what I call low-hanging Cocoa fruit. So they're things that you get a big bang for with little effort.

And I'll go ahead and demo those two. And then we're going to have one of your own, third-party developer, Scott Thompson, come up on stage. And Scott was one of the people responsible for taking what was a large-scale, legacy, Windows-only application and then putting a Cocoa front-end on that and turning it into a cross-platform application. So you'll get to hear some of his experiences in doing that. And we'll try and leave some time for Q&A afterwards.

So regardless of what framework, language, or development environment you're writing for, all successful applications have to follow the same simple guidelines. We want to solve a problem for our customers quickly. We start with the target customer and a great idea. So regardless of, for instance, if we're writing maybe a ringtone editor for a cell phone or perhaps like a high-end, vertical market, expensive application that's going to process and analyze MRI scans, we want to follow these same simple guidelines. You design for Aqua and Mac OS X, keep your UI simple, maybe then we let some people test it, iterate on that UI, different prototyping of our UI, adopt other killer technologies, so whether that's maybe core audio on one side or core image or core video on the other.

and then we want to deliver something of high production value, something which differentiates our application from that of our competitors. Well, Cocoa was designed with all these goals in mind. In fact, I think when you look at Cocoa applications, they have a reputation for having a clean, crisp user interface and application behaviors which we and our users come to demand, things like cut, copy, paste, undo, redo, scriptability, accessibility, and a whole lot more.

So Carbon started out as just a porting layer, but since that time, it's turned into a whole lot more. So let's go ahead and see what a modern Carbon application is. I'm glad to see that all of you have already compiled your applications for Universal and are on Xcode.

Modern Carbon applications lay out their user interfaces with Interface Builder. Should be using core foundation for the base types, things like CFStrings to abstract Unicode, CFArrays. So you should all be familiar with the retain, release, reference counting memory management models. Carbon uses procedural-based APIs to interact with the system. It's probably been drilled into you pretty good by now. It shouldn't be using Quick Draw and should have adopted vector-based drawing in the way of Quartz.

and we use Carbon Events as a method for overriding default system behavior and as our event model. And we use HIViews and composited Windows, as well as modern applications are bundled, so we keep our localizations in Lproj folders, images specific to our application in the resources subdirectory, an Info.plist which describes our application. And we shouldn't be using any deprecated APIs, right? So let's take that evolution one step further and take a look at Cocoa. Well, Cocoa applications are also universal, also lay out their UI in Interface Builder.

Cocoa applications rely on foundation for the base types. And through toll-free bridging, we can simply cast things like NSStrings to CFStrings, or CFArrays to NSArrays. The big difference between Carbon and Cocoa is that Cocoa uses object-oriented APIs when interacting with the system. Cocoa uses things like NSImage, NSBezierPath for their graphics model. NSImage and NSBezierPath simply lie on top of Quartz.

And Cocoa uses delegates and notifications as its event model and method for overriding default system behavior. Later on in the session, I'm going to go over an example comparing Carbon events to delegates. and Cocoa Applications will use NSViews, which are really very similar to HIViews. Cocoa Applications are also bundled and also should be using deprecated APIs. So hopefully by looking at these two lists, you realize that you probably know a lot more about Cocoa development than you thought and definitely more than someone that's coming new to the platform.

Well, I felt obligated to throw in at least one architecture diagram here. So we have our typical Darwin-Kernel graphics, the two application frameworks which we're interested in, Carbon and Cocoa, and Aqua above that. But in reality, over time, Carbon and Cocoa have been using more and more code, more and more similar code. I mean, we access files, and the resource works of those files the same way. Our Carbon and Cocoa applications get launched the same ways. Our icons are the same, so we use the same artwork. Now we're introducing things like core text.

So over time, we've had this core services layer, which has been growing and growing. And this is a common API set that's common to both Carbon and Cocoa. So in reality, the architecture diagram looks a little bit closer to this. So what is Cocoa? Well, it's the most advanced framework ever.

I got this email a few weeks ago and it reads, "I finally quit MetroWorks this year and have moved on to Aspire. I've been learning Cocoa and to my great surprise, I love it." This was sent to me by Joseph Wankerl. A lot of you may already know him. He used to work at MetroWorks.

But when I read this, this really means a lot. I mean, here we have a long-time Carbon, Power Plant, and MetroWorks developer who just started learning Cocoa and he loves it. And I think this is a common sentiment among a lot of developers who start picking Cocoa up.

So let's dig a little bit deeper. One of the really neat things about Cocoa is that we use a few concepts pervasively throughout the entire Objective-C frameworks. So a lot of time you hear analogies of Cocoa being compared to things like LEGOs. And it's really kind of true in that because we use these same conventions throughout all of the frameworks, we can start to adopt new technologies without really having to know too much about them, without having to be experts. So for instance, if I want to add something like speech to my application, I can make a pretty good guess that I'm going to have to allocate and initialize some speech object and then start sending it messages.

and I can be rest assured that the experts that know everything about speech have already implemented the default behavior back in Cupertino. Now, if I want to start overriding the default behavior, that's when I have to start reading up on the material and becoming an expert on myself. So Cocoa is a full-featured application framework, so it contains advanced controls, things like NSTextView, NSOutlineView, the WebKitView. The WebKitView is really almost a full web browser packaged down into a single view.

Application behaviors, as I mentioned. You get a lot of this for free or with really little code, so things like cut, copy, paste, undo, redo, scriptability, accessibility. And in 10.4, we announced the serialization of your entire object graph through Core Data. And then just on Monday, we introduced Core Animation and Animation Kit.

In general, Cocoa will handle all these default behaviors for you and allow you to build more consistent applications and also allowing you to focus on the core of your code, so the intellectual property that you're interested in. Another neat thing about Cocoa is that it is a rapid application development environment, so you can quickly prototype new UIs.

You develop your UI, you can go ahead and change it without really having to write little code. Interface Builder becomes much more powerful when dealing with Cocoa applications. I'll show you a demo of this later. But not only is it a great prototyping tool for rapid application development, it's a full-featured, rich application development environment that will let you ship large-scale, shrink-wrapped applications.

So why use Cocoa? Well, you get these well-integrated system behaviors for free. And really what I mean by that is, for instance, when I work on a Cocoa application, I almost think of it like I have a whole team of Apple engineers working with me. So I'm concentrating on the core of my application code, and this team of engineers is back in Cupertino making sure that all my Mac OS X specific code is handled for me. So when we moved to different architectures, from PowerPC to Intel, I can be confident in knowing that my team of engineers back at Apple is handling all of these Indian issues, byte swapping issues for me.

When we announced things like resolution independence, I don't have to be so concerned about what the difference is between pixels and points, upgrading my art to high resolution art. I know this team of engineers is on top of this issue, handling all this for me, and I can concentrate on the core of my code.

It's developed with Mac OS X. What I mean by this is Cocoa is actually part of the operating system. So as we introduce new features, those APIs and those features are introduced through Cocoa. So in the past, when we introduced new technologies at Apple, there was always this lag time between the time when we introduced this technology and then the time between we would see the APIs appear in frameworks such as PowerPlant.

It integrates well with development tools, so I'm sure that you're all aware of this. I mean, a lot of you know that Interface Builder behaves a lot better with Objective-C and Cocoa-based code, and then from the announcement on Monday at the tools state of the union, I think some of you may have seen the code refactoring, and this is truly amazing.

We lay out our class. One of the things that he did was just change the name of his instance variable, and then it will go ahead and pervasively change the name of my instance variable throughout all my code, but it doesn't stop there. It goes ahead and changes the names of all my getters and setters, and not only that, it will actually look inside my nib files, and references to that instance variable get changed inside my nib files, too. And you only get this tight integration with Objective-C and Cocoa code.

So we've spent many years and millions of man hours developing what we think is a rich, full-featured framework in Cocoa. We are dedicated to supporting Cocoa into the future, and I think everyone can realize that. And probably the biggest reason why you're all here today is the ability to easily integrate our latest killer technologies. Things like Core Data, Sync Services, Quartz Composer, Instant Message Framework, WebKit, Core Image, QtKit, Address Book, PDFKit, Bluetooth, and there's a whole lot more. I mean, we have .Mac, animation, and so forth.

One of the big directions of Carbon in Leopard is better integration with Cocoa. So to give an example of that, everyone knows Quickdraw was deprecated and now with 64-bit it's completely removed and unsupported. Well, what kind of fell off of that was named cursor support, for instance. Named cursor support was reliant on Quickdraw.

So then the question comes up, what kind of API are we going to provide to replace the named cursor support API? So the first thing we do is take a look to see what NSCursor has to offer. Well, it turns out NSCursor is already 64-bit clean and has all the functionality that we need.

So the next question comes up, do we write a Carbon API around NSCursor or do we ask Carbon developers to call NSCursor directly? Well, a common theme over the last couple WWDCs has been that we are going to produce a great technology and API set that goes along with that. We're not going to be in the business of creating great technology and then releasing two APIs and supporting those two APIs. So the decision was made to go ahead and ask Carbon Developers to go ahead and call NS Cursor directly.

So, Cocoa design. As you know, Cocoa is object-oriented, so you're going to have to become familiar with those object-oriented paradigms, things like subclassing, delegation, inheritance, sending messages to objects, or as we think in C++, maybe invoking methods. Cocoa is based on a model-view-controller design. So I think most of you understand what that is.

When we lay out our user interface as the view and our model proprietary data underneath is the model and we provide controller classes which mitigate the data and information flowing between the two. And this is a great design pattern. It leads heavily towards portability, maintainability, and so forth.

When you design for the MVC model, you should just always ask yourself, from the user's perspective, how does the user interact with my data? And likewise, from the application perspective, how do I manage the data from the model-controller side? When Scott comes up, he's going to talk into a little bit more detail about how he was able to take advantage of the model-view-controller in bringing Mindjet over to the Mac.

Excuse me, Mind Manager. So how do you get started with Cocoa? Well, first step, move your code to Xcode. I'm glad I think everybody's hand was raised. We've already done that. And the next step is to learn the differences in Interface Builder. So let's take a look at that right now.

So when we lay out our user interface, here's a sample Carbon user interface, my registration dialog. I'll go ahead and lay out my user interface until it's just the way I like it. Then typically, we'll take a step back and take a look and we'll see which fields do we have to access. In this case, we're going to access our editable text field. So typically, we'll assign it a signature and an ID. And then we'll go ahead and get that through the get control by ID.

And then again, we'll go ahead and see which actions we need to take. So in this case, when the user clicks the OK button, we'll want to assign it a command to take some sort of action. Then we'll go ahead and parse that command through our Carbon Event Handler, nest it in there. We'll check to see what kind of a command it is. And finally, we'll call a routine in our model class called Validate Registration here.

Now let's go ahead and see how we do the exact same thing in Cocoa. So I tried to lay out the user interface the same way. One of the first things that you're going to notice here is that cube on the lower right, and it's called Registration Controller. That cube actually represents an instance of my Registration Controller class, my own class.

From that point on, we can then drag connections into our class. So in order to gain a reference to the EditableText field, we simply drag a connection between our Registration Controller and our EditableText field. And then we'll go ahead and name it RegistrationCode. So now we actually have an instance variable set up within our RegistrationController class, which references that control directly. It's quite easy.

Then again, we'll go ahead and take a step back and see which actions we're going to need to take back, we're going to need to set up. So again, we're going to want to set the OK button. So we'll go ahead and drag a connection from the OK button to our Registration Controller class, and we'll assign it a name, Validate Registration. So after we've done all this, we've got a small class now called Registration Controller. When the user clicks OK, it will call our Validate Registration method directly, and from that method, we can access our instance variable, registration code. There's really no code to be written here.

So Cocoa is not a separate box. It's not isolated in its own environment. That kind of reminds me of a story. I go to the Silicon Valley Cocoa Heads meetings when I can, and a while ago, maybe about a month or two ago, I met the Yahoo Messenger for the Mac engineers, and then again about three weeks later, I think this was about the day after they had released their 3.0 for the Mac beta, I saw Carl, one of the engineers, eating lunch on our campus.

So I asked him if he wrote the client in Cocoa, and he said, yeah, mostly. So I asked him what he meant by mostly, and he said, well, we share this large C++ source base between our Mac and our Windows client. Well, in my mind, this is a Cocoa application. I mean, this is a typical way of writing a cross-platform Cocoa application. You provide your view and your controller classes, which interact with the operating system, and then you have your proprietary C++ model code underneath.

and Scott are the first to introduce the new Carbon and Objective-C framework. Cocoa can easily interact with other subsystems like Carbon, BSD, and Quartz. With Objective-C++, you can easily mix and match C, C++, and Objective-C all in the same file. Scott, again, is going to talk a little bit more into detail of how he was able to take advantage of that.

So the next step is to learn Objective-C. So if I were to take a typical source file and hand it to a Carbon developer, Carbon developer will typically look at it and ignore everything in those crazy square brackets. If I were to take that same source file and then hand it off to a Cocoa developer, Cocoa developer is probably going to ignore everything that isn't in those crazy square brackets. Well, it's really not that bad. We have a great document online called the Objective-C Programming Language, and I promise within a few hours, a day at the most, you will understand enough Objective-C to get yourself started.

But you should also know that Cocoa applications can be written in other languages. So we actually have a session on Friday morning which talks about writing Cocoa applications in Ruby and Python. But you should know that any interpreted language is always going to suffer performance problems over a compiled language.

So let's take a closer look at Objective-C. Here's a typical C function call. Set sticky note dimensions. We're going to pass in a pointer to my sticky note, some dimensions, and a Boolean. Maybe this is to make it visible. I'm not sure. Well, let's take a look and see how we write the same thing in Cocoa. We'll start off with the brackets. And then we'll set up our object so the object can kind of be compared to our pointer.

and then we'll go ahead and set up the arguments. So this is actually, we're going to send the object, my sticky note, the message to set the width to 50, height to 100, and to animate the transition. So by looking at this, you can tell that this is actually much more readable. I think this is almost self-documenting. Maybe you can get rid of your comments.

Let's take a look at another example. So here we have some embedded brackets. So probably from the last slide, you've already learned enough Objective-C to tell what this is going to do. We're going to start from the inside brackets and take the color of our last sticky note and assign that to the current color of our current sticky note. But actually, this is kind of interesting. Just by looking at this one line of code, I can tell quite a bit about what the class actually looks like. So let's take a look.

Virtually all classes in Cocoa are in one way or another derived from the powerful base class NSObject. So NSObject provides, among other things, things like the reference counting retain-release memory management model, and, of course, with Objective-C 2.0, if you're targeting Leopard, you can use the garbage collection. But we can have a good idea that we've got an instance variable named color.

Now in Carbon, for instance, our getters and setters are typically named things like getControlValue and setControlValue. In Cocoa, things are done a little bit differently. Our getter is named the exact same thing as our instance variable. So color would be the name of our method to get the color. And setColor is our setter.

Small s, set, capital C for the color. Now it's very important that you follow these coding conventions set up by Cocoa rather than taking all the coding conventions that you've developed over the years and pushing those into Cocoa. Reason being, a lot of conventions are built on top of this.

So, for instance, in Cocoa, we have concepts of key-value coding and key-value observing. Key-value observing allows you to watch an instance variable, and when the instance variable changes, we can take some action. And then on top of key-value coding and key-value observing, we build bindings on top of that. So if you start to break down the low-level conventions like the getters and setters, the rest of those conventions are going to go out the door.

So here, let's take a look at comparing Carbon events to delegates. So here we have part of a function to constrain a window to only grow it horizontally, not vertically. So typically what we'll do is we'll install a Carbon event handler on a window, take a look at the k event bounds changing Carbon event. Then from within our routine here, we'll go ahead and get the rectangle of our previous window, pull out the rectangle of our current window.

change the rectangle so that the current Windows rectangle matches the previous window rectangle, maybe then we'll call size window and return no error or course those parameters back in and return back event not handled. We go ahead and write this code. Send it out for testing. Everything seems to work fine. Okay. We think we got it. All of a sudden we hit the Zoom box. Boom! Takes up the whole screen again. Okay. Not a big problem. We'll go back, look at the code, try to add the clause in there to handle the Zoom.

We think we got it now. At least I think those are all the cases. I'm pretty sure anyway. Those are all the cases I wrote in here. But let's take a look and see how we do the same thing in Cocoa. So Cocoa has this concept of delegates. Delegates allow one object to receive messages from another object to override. So typically we'll use delegates to override commonly overridden system functionality. Let me try and describe that a little bit better.

Here again, we have an app controller class. If you look at small samples on the web or tutorials, they'll typically name their controller class app controller, so I did the same thing in this case. What we want to do is make our app controller class a delegate of our window.

So from Interface Builder, we'll simply drag a connection from our window to the app controller and assign it as our delegate. Then through dynamic binding, the NSWindowController is going to say, app controller, do you respond to the message, window will resize? And if we do, it'll call us. And it's really just one line of code. We go ahead and set the height of our window to match what the height used to be, and then we return that size. So there's really very little room to make any errors here.

So here are a few tips and tricks that I've picked up along the way. So perhaps you have a large source base. You've got hundreds, maybe thousands, of source files in there. Maybe you're compiling in open source projects. Well, you may not have the patience or the ability to go through there and rename all of your source files to end in a .m or .mm extension if you're doing Objective-C++. So what we do offer is a build setting. It's the compile sources as build setting. This will allow you to put Objective-C code directly into your .c files and it will invoke the Objective-C flavor of the compiler when compiling your files.

Now, if you run into errors in this case, for instance, if you're using keywords used by Objective-C, there's another option. You can do this on a file-by-file basis. So here we can do a get info, in this case, a get info on main.c, and we can coerce its file type to be sourcecode.c.objc. It's a great tip.

Next one, CodeSense. So I'm sure most of you are already using this. This is code completion. Objective-C is really the easy part when you're adopting Cocoa. The hard part is you're being faced with literally thousands of new APIs. But the good news is that because of the code conventions used, after a while you can start to guess and understand what the APIs are going to be named. So before you start looking through the header files or looking through the documentation, you might start taking some guesses. So here I want to maybe create a subview. No, I want to add a subview. Yep, there it is.

You guessed right. Add a subview. Hit return. It puts it in there. And then just like Carbon, you use control slash to advance the highlight from one argument to the next. So after you've got the basics, I recommend that you start learning the more intermediate to advanced topics. Things like key value coding, key value observing, as I mentioned earlier, and then bindings on top of that.

So let's talk about migration strategies. Which framework is right for me? Well, both Carbon and Cocoa are able to create 64-bit universal binaries. So why not take advantage of both? You can go for a gradual adoption strategy. So I remember when Mac OS X first came out, some developers decided to maybe create their next window using Carbon Events.

And the way they would do that is encapsulate all their code for creating the window, installing the event handlers, and handling the events all within one file. Right? After they began to become familiar with Carbon Events and began to like them and understand how elegant they were, they start to move these changes pervasively through the rest of the source space. Slowly, you bump up the sleep time on wait next event.

After you feel comfortable, you change wait next event to run application event loop, and you're off. You can kind of adopt the same strategy when looking at Objective-C and Cocoa. You can start by adopting something like a Cocoa service, such as the font panel, color picker, or spelling panel. or with Leopard, you can now embed an NS view directly into your Carbon application. Or you may choose to make your next window a Cocoa window.

So let's look at some tips and tricks when dealing with a hybrid application. The first one, you have to start including NSApplicationLoad. Just get used to it. Otherwise, you're going to see bugs and beat yourself up about it. So get used to including NSApplicationLoad. Calling it multiple times simply is benign. It'll simply check to see if the NSApp variable has been initialized, and if it has, it'll return.

Another tip is that Interface Builder 2 can actually read and write your controller files. So one of the really neat things is, from Interface Builder, after you've dragged all these connections around, set up all your instance variables and method names, you can actually go to the Classes menu and choose Create Files for Window Controller. This will generate your complete header file for the class you just created in Interface Builder and a stub implementation for the implementation side, and put those files directly into your Xcode project.

From Xcode, then, you can begin changing them, and then sync them back up with Interface Builder any time you want. This is a really neat tip to get yourself started. You drag those connections. You don't have to worry so much about the syntax because it will create it for you, and then you get going.

So let's talk a little bit about the Carbon-Cocoa interaction. So in Tiger, fully supported is any non-UI code. So for instance, you can call the spelling checker directly from Carbon. It'll be fully supported. Modal panels in the other environment, floating windows, palettes, also fully supported in Tiger. supported with caveats, creating a Cocoa document-based window from your Carbon application. I remember reading on the Carbon dev list a while ago that, for instance, window cycling didn't work quite right when creating a Cocoa document-based window inside of a Carbon application.

There are a few other minor glitches like that that you can find within the Windows menu, and these are all issues that we're addressing for Leopard in Carbon right now. Embedding an NSView within an HIView. This works. The goal is to be able to embed any NSView within an HIView. Actually, I should rephrase that.

Any NSView which draws on its main thread in an HIView. But this is a Leopard-only feature. Sheets and drawers in Windows of the other environment. This is a feature which is planned to be supported in Leopard, but on the seed that you have right now, I don't believe that there's support for it.

So I'd like to quickly go over some of the demos that we included with this session. I believe if you go to the WWDC attendees area under session 129, you can find all these demos and if not, they should soon be available. The first one is the Carbon with Cocoa web window.

This is a Carbon application which launches-- A web kit, web browser-based window, Cocoa window, from your Carbon-hosted application. For this sample, I included a step-by-step tutorial of exactly what I did in Xcode and exactly what I did in Interface Builder to do this, and a little bit of the thought process that went into doing this from the Carbon perspective again.

and then based on this sample, I wrote two other samples. One of them is the Carbon Quartz Composer TV sample. Again, this is a Carbon-hosted application which brings up a Cocoa-based window and we have a complete Quartz Composer composition in here which has bindings running and everything. It makes a pretty splashy demo. I'll show it to you in a minute.

The next one is Carbon Cocoa Core Image Tab. This is again a Carbon application and in the Cocoa side of this, on the Cocoa window, I made a tab-based web browser and then I included some core image effects. So when you switch from one tab to the other, we can use some core image effects in here and this works back to Tiger. It's really neat.

In fact, when I wrote this sample, I was literally dragging people in from the hall to show them because it really makes that wow factor, I think, that Bertrand was talking about. Next one, like I mentioned, we're asking developers to start using NSCursor and because I mentioned NSCursor in the presentation, I wanted to include a sample which shows exactly how to use NSCursor from a Carbon-hosted application and in the sample, I actually write some Carbon wrappers around NSCursor. I shouldn't say I, I should say we on this one. So, We have the HIView NSView. This sample is a leopard-only sample, and it shows how to embed an NSView in an HIView. So real quickly, if we go over to the demo machine.

So I just want to real quickly show off some of these samples here. Here's the first one by which the two other samples are based on, the Carbon with Cocoa web window. It's quite simple. We have our Cocoa window here. Excuse me, Carbon window on this side, named Carbon window. Cocoa window here. And as you can see, it's almost like a full web browser. We can click in here.

Let me try and see if we can load .mac. We'll load QuickTime. All the links seem to work. Backwards, forwards, and if you notice, the URL and the title also change with my links. And I did all this with really very little code because the WebKit view is really a full-featured view, which allows me to kind of set up some bindings.

So without having to be an expert at bindings, I can set this up directly from Interface Builder, and it all just works. So let's go ahead and take a look at some of the other samples. Here's that Carbon Cocoa Core Image Tab sample I was talking about. Let me go ahead and set this one up. Let me get something fun here.

Okay, so I have two, that's not a real fun page, but we have two websites here and watch what happens when I click between one and the other. Here, let me slow that down a little bit by holding down the shift key. This is really easy to do. You can just grab the source code, integrate it right in there, and I add a menu to do different core image effects.

So, and this works in Tiger, so it doesn't use any of the core animations, all core image. And the Quartz Composer TV sample, so we have our small Carbon window here, we'll open up our Cocoa-based window. The camera's starting. Looks like the camera-- oh, there it goes. And it actually uses bindings. So actually, if I change the title here, it's all going to be live. If you look at the orange title above, we'll go ahead and put 2006 in there. Hit Return, and it all updates live.

And lastly, we have the sample which demonstrates how to embed an entire NSView hierarchy within our HIView, and that is in the HIView NSView sample. And again, the last sample that we have here is the Carbon Cocoa Picture Cursor, which just demonstrates how to set the cursor through the NSCursor APIs. If we go back over to slides.

So with that, I'd like to welcome Scott Thompson, talk about his experiences bringing Mind Manager to the Mac. All right. Hello, how are you? Thank you for having me. I appreciate it. My name is Scott Thompson. I'm the lead architect for cross-platform products at Mindjet. And I'm sure some of you are wondering why is Scott here.

You heard Deric speaking about the fact that I work on an application that used to be a Windows application, but why would I be here for a Carbon session? Well, in a previous life, I was known as the Macintosh technical lead for Macromedia Freehand. And Freehand was one of the very first applications ever ported to Carbon and moved to Mac OS X through the Carbon APIs. Freehand is a very large application. It took us a lot of work to do it.

And the last time I was on this stage, I was actually demoing it in the WWDC keynote. Now I work at Mindjet, and we work on a program called Mind Manager. Mind Manager is a legacy Windows application that we've moved to Mac OS X using Cocoa, but our development team was actually peopled with people that were Carbon developers. One of us had done some Cocoa. But we'll talk about that, and I'm here to tell you about my experiences.

That's a very black slide. Ah, I pushed the wrong button. It doesn't work. All right, so what is my purpose here? Well, we're going to explore the case study of MindManager and what we did to make MindManager work on the Mac. We're going to discuss some of the architectural decisions that we made in doing that as a large cross-platform application.

How does that fit into the Cocoa universe? And how do Carbon Developers do that? We're going to offer advice from Carbon Developers who've been there before. We've made the transition from Carbon to Cocoa. Maybe we can give you some hints to help you along the way, offer you signposts to put your feet on the best path to bringing your code forward.

What will happen if I'm successful? Well, hopefully I'll answer some of the questions that you might have about Cocoa. I'll help you visualize how Cocoa can fit into your development plans, maybe steer you away from a couple of the pitfalls that we fell into so you don't have to wallow in the mire with us. And if I inspire you to try Cocoa at home, then I'll have done my job admirably. Thank you.

So let's talk about MindManager. What is MindManager? MindManager is a productivity application for information management. It's designed to help you capture, share, and collect your ideas and organize them. MindManager is Mindjet's flagship product. It has a nine-year history of development on the Windows platform. By the time we started the project, it was approximately one and a half million lines of Windows and MFC code, all of it written, of course, in C++.

The first thing we learned was that MindManager was already mostly MVC-factored. They've done a very good job of separating their core code away from their user interface, and we'll see some of the implications of that. Now, this is not a MindManager sales pitch. If you're interested in learning more about MindManager, you can go to www.mapthemac.com or catch me around the sessions, and I'd be happy to show you MindManager. One thing to note about MindManager, it helps you capture ideas. Developers typically have a lot of ideas. We found it to be a very handy development tool.

All right, the project, what we had to do. The idea was, of course, we wanted to create a Macintosh version of MindManager. The reason we wanted to do that is because MindJet had had a lot of feedback from MindManager customers, and they wanted to bring, you know, they noticed a good synergy between the sort of things that MindManager does and the sort of creative people you find on the Mac.

So there was already high customer demand. And after we came up with our first beta, we got a lot of comments from users that said, "Oh my God, finally, I can finally get rid of that Windows laptop I've been keeping around just to run MindManager." So we had two big goals as we started the project. We wanted to make sure that we were making an application that was MindManager. We didn't want it to look something bizarre.

And we want to make sure that it was a Macintosh application, not a badly ported Windows application. So I'm sure you've all seen those. We wanted to make sure that you didn't see another one. The total time that we had to do the project for the first release was approximately 18 months.

The team that we had, starting with Mindjet, was we had Larry. Larry had absolutely no Mac experience whatsoever, but he was our tie to the past. He'd been working on Mind Manager for a long time. Then there's me. I'd done mostly Carbon programming on big Carbon applications. I was a Cocoa hobbyist. I'd pulled out and done some tutorials and those sorts of things.

We had Jeff. Jeff, as well, was largely a Carbon programmer who hadn't done much with Cocoa. We brought in Glenn. Glenn was our Cocoa ringer. He'd actually had five years of professional development experience using Cocoa. Then we had Eric, Jim, and Paul, who were three contract engineers. They helped us out. It was sort of a mixed bag. Some of them had some more Cocoa experience than others, but by and large, we were a Carbon team trying to move into a Cocoa world.

The timeline for our project ended up breaking out this way. We spent the first five months doing sort of strategy and setup. We had a large application to move over, so we had to nail down exactly which features we were going to bring over, which ones we weren't going to be able to bring over for technical reasons or time reasons and all those things. We also spent the first five months getting some of the low-level libraries to rebuild, things like the XML layer and encryption, and we have some code to handle zip archives and things.

So the actual application development took about 12 months. So from the time we actually started writing Cocoa code and designing the user interface, it took about a year, and we shipped in May 31, 2006. So essentially, we built a Cocoa application, a fully-featured Macintosh application, in about 12 months using some of the help that we had from the Windows code.

So a big part of our success was based on our application strategy. And our application strategy in term is based on Model-View-Controller. The first thing that we did, though, was we noticed that we were going to have what we call a core and edge structure. So core is the platform-independent code. That's the C++ code that's shared with Windows and those sorts of things. The edge code would be the platform-dependent code, so any of the code that you use to do the user interface.

What we decided for our application strategy was we were going to use the existing C++ data model that Mindjet already had. They had put a lot of work into developing their data model, getting it ready. We were also going to use a lot of the existing commands and notifications, those portions of the controller layer that knew how to manipulate the model. We're going to keep up with those. Of course, we decided, being Carbon programmers, that the Macintosh edge code would all be done in Cocoa.

So when you do something like this, the place where things get really exciting is at the interfaces between layers. I mean, that's where, you know, if you think about it, we've got lots of idioms that go along that way. We have where the rubber meets the road, between a rock and a hard place, those sorts of things. So we spend a lot of our times in those kinds of nooks and crannies. Some that we ran into in particular were, of course, the user interface versus the business logic.

We couldn't reuse a lot of the user interface controller layer from the Windows side because we didn't want our application to look like a Windows application. We wanted to do a Mac application, so we needed new Macintosh-specific code for that sort of thing. Platform-dependent code versus platform-independent code was another interesting transition layer. And along with the platform-dependent and independent, we also had the C++ versus Objective-C transitions to deal with.

So the way that we did this was we relied heavily on the Model-View-Controller model. Now, Deric, you're bound to have run into Model-View-Controller at many places up to this point, and it was a really valuable tool for us because we knew we wanted the view side of things to be in Objective-C.

We knew we wanted the C++ side of things to be in C++, but the question is, what do you do about that controller layer? I mean, how do you deal with the controller? Well, the way that we dealt with it in our application was we took the controller layer and we split it, not necessarily right down the middle, but into two pieces.

So if you view the controller layer, one side of it as, how does the user interact with my data? What sort of gestures are they going to use? What sort of things is the user going to do? And you look at the other side of the controller as, what commands am I going to send to my model to actually make changes to my model? Then this split makes a lot more sense. Now, as it turns out, it also happens to correspond with some of these interfaces we've been talking about. This entire side of the diagram was what we were going to write in Objective-C, or in this case, we actually used Objective-C++ because Objective-C++ can talk directly to C++.

The other side of the diagram, of course, was going to be the C++ legacy code that we inherited from Mindjet, and that's how we were going to manipulate our model and do serialization and those sorts of things. So it also corresponds roughly to the platform independent and platform dependent.

Transition layers as well. So by and large, the view side and the controllers that went into the view side were all platform-dependent code dealing with the Macintosh user interface. And as we mentioned, we've got the legacy code that's shared with Windows for the platform-independent side. So we had to touch Objective-C, and I know that that's a sort of a large issue for a lot of people. It causes lots of consternation on the development list and things like that.

It is true that Objective-C does look different. There are square brackets. They end up in your code, and you're like, eh, what's up with that? But that sort of, the oddness of it goes away very quickly. There's a whole lot more to learn about Objective-C than just the syntax. The syntax is the smallest part of it.

You also have to learn about how objects are created and released. You have to learn how methods are dispatched and those things. But once you've learned those things, you can apply them to so much more than just Cocoa. So the sort of canonical example of this is Core Image.

If you wish to use Core Image from inside of a Carbon application, you have to go through the Objective-C API. But in this case, Core Image is not part of Cocoa. Core Image is part of that Core Services layer. And, of course, this week I learned with you about Core Animation. Which is also down sort of in the Core Services layer. It's an Objective-C API, but it's not necessarily a Cocoa service.

The final thing I want to mention about Objective-C is that it does have some advantages. There are reasons that Apple uses Objective-C, and it takes you a little while to recognize some of those reasons. But once you get it, once you understand why they're doing what they're doing, it makes it a whole lot easier to swallow.

So let's talk a little bit about Objective-C++. I mentioned that most of our platform dependent code was written in Objective-C++. As Deric mentioned, it allows you to combine C++ and Objective-C in the same file or often in the same line. If you want to call an Objective-C method and you have to make a C++ call in the middle, you can just call it normally as you would. It brings some familiar C++ features that I happen to like. I like strong typing. I like the ability to declare variables anywhere. I know some people don't like that, but I find it very handy.

And when you're doing this, your Objective-C++ controllers become these islands of information exchange. What I mean by that is if your core code, if the model has some sort of notification that it needs to send back to the user interface, it's going to have to make one of these transitions from C++ to Objective-C. What it can do is sort of hop off of one of your controllers, send it to your controller, and your controller can rebroadcast the notification as an Objective-C message.

Or you can go back the other way. If the user clicks on a button in your user interface, that Objective-C message will go to the controller, which is an Objective-C++, and it in turn can call a C++ method. Finally, using Objective-C++ is very easy, as Deric pointed out. We use .mm files for all of our controllers, but occasionally we have to go in and actually mark one of our C++ files is needing Objective C++.

[Transcript missing]

So let's talk about Cocoa itself. Cocoa contains some really great frameworks and this plays into the idea that Deric kept mentioning that it brings a lot of functionality together for you, you know, for free. The user experience for us came together very quickly. We didn't have to do a whole lot to, you know, get standard buttons working and all that kind of code wired up to our code. So you get lots of standard behavior for free and another interesting thing to note is that we didn't have to use all of Cocoa and Deric mentioned that Cocoa is not a box.

It's not going to lock you in. As it turned out, because we were using the C++ code to handle the commands to the data model, the way that Cocoa handles undo and redo through the Objective-C dynamic dispatching was sort of very inconvenient for us. So we simply, you know, rerouted those menu items to our C++ code and went out from there. And as Deric mentioned, Cocoa is actually really great as a prototyping tool. It allows you to wire together a user interface quickly and your UI designers will really like that.

So you can take the boy out of Carbon, but you can't necessarily take the Carbon out of the boy. One effective strategy that we used was to actually drop at certain levels in our code. We actually avoided a C++ to Objective-C transition where it wasn't necessary. So, for example, we had the Windows-based file classes that we wanted to reproduce. And we wanted to sort of keep some of the same behaviors there.

So rather than calling back out to, say, NSFileManager or NSFileHandle or something like that, we just basically picked up the old Carbon File Manager routines, which are actually, I think they're now part of core services, and called those. Similarly, when we were doing our graphics drawing, we'd get to a certain point in the code and we wanted to have the exact same C++ code driving the rendering in the same order so that things didn't look different between the Mac and the Windows inside of documents.

Rather than making a transition back out to Cocoa and actually using NSBezierPath and those classes, we actually jumped straight to the Quartz 2DC interfaces. We used Core Foundation an awful lot. And Core Foundation becomes this really nice transport mechanism for moving information from the C++ side to the Objective-C side because of the toll-free bridging that Derek mentioned. If we had some C++ code that needed to return an array, we could just package it up in a CFArray. Pass it across the boundary and typecast it to an NSArray and away you go.

So let's talk a little bit about getting started from my perspective. As Deric already mentioned, the first thing is to realize that you already know a lot about Carbon, about Cocoa development. You already know a lot about Carbon development too. You know, application bundles aren't going away and they're the same on either platform. Lots of application functionality is down inside those core application services layer and you may already be familiar with a lot of it.

Aqua hasn't changed, so all the work you put into user interface design, you might have to redo the nib file, but you don't have to relay out your controls and and all that kind of stuff. Capture the basics first. So start with some of the simple tutorials. There's an awful lot of stuff in Cocoa and Cocoa related. The key value coding, the key value observing, bindings.

These are very exciting technologies, but you sort of have to get in the right mindset before you can really pick them up and use them effectively. So start with some simple tutorials. And begin with a good grounding in the basics. So some of the basics you'll want to know. You'll want to know about some of the idioms that Cocoa and Objective-C use because they're patterns that are a little bit different than the way C++ does things.

In particular, these are just some examples. The object life cycle, the way that objects are constructed and destroyed, the way you get into the middle of that process and interject your own code into the initializers is different in Cocoa and Objective-C. Mutable versus immutable. Mutable objects are used pervasively throughout the Cocoa frameworks.

You may already be familiar with some of this from the core foundation work you've already done, but it takes on a sort of a whole new meaning in the Cocoa world. Derek mentioned the delegation instead of subclassing. One of the things that I always like to point out to people is that once you've learned these things, they don't exist in a vacuum. You're adding tools to your toolbox.

I found places where I could take something I learned from the Cocoa side of things and apply it in the C++ code. So, you know, if you get really bogged down and, "Oh, I hate to have to learn this stuff," just realize that you're still learning. So that's always, there's something to be said for that.

As Derek mentioned, you can start using Objective-C from your Carbon app. Core image is one of my favorite tinker toys. I imagine that core animation would be one if it was around before I started this slide. Those are examples of Objective-C APIs you can make calls to from inside of Carbon. app, and Derek provided you with some samples as well.

One of the most interesting things about Objective-C is this idea that you can send a message to any object at runtime, and the object will decide whether or not it wants to actually handle that message. Much of the Cocoa magic is based on this, and it does take a little while to get your brain around to working in that mode. I have a little bullet point here. The implications of late binding are pervasive, but not immediately obvious.

The reason for this is that you'll find that as you're going through your code, you'll run into this brick wall and you're like, "How does this happen? How is this code getting invoked?" Whenever you hit one of these roadblocks, look and see if there's some dynamic method dispatching going on that you weren't previously aware of. If you hit a roadblock, look for it to see if you can find out how to get around it through the magic of Objective-C.

[Transcript missing]

So I wanted to end with a quote, and this is a quote that one of our developers, Jeff Lynch, heard when he was at the Big Nerd Ranch. And it's, when you find yourself working with Cocoa, if you find that you're writing a lot of code to implement some basic functionality, you're probably doing it wrong.

Now, it's kind of a flippant maxim, but it was something that proved to be true for us repeatedly in our development. We'd find we were writing a lot of code, trying to get something done, and if we had just taken another five minutes and stepped back and read some of the documentation, we found that it was already there for us. So that's all I have, and I'll turn it back over to Deric to help you wrap it up. Thanks, Scott.

Here's my email address. You can all email me. In summary, a few things I'd like you to take away is that, first, you don't have to start from scratch. Objective-C and C++ play nicely together. The framework does a whole lot of work for you, so you don't have to do it. And this stuff really is fun. Everybody that starts writing Cocoa applications, you get a whole lot of action with very little code.

So with that, as Scott mentioned, list.apple.com is a moderated list with over 4,000 members. If you want to go for the entire Cocoa immersion, I highly recommend the Big Nerd Ranch. You spend a week out there thinking nothing but Cocoa. Aaron Hilligast also has a book, Cocoa Programming for Mac OS X. And there's also a website, Cocoa Dev Central, which provides a whole lot of tutorials. So as you start to learn Cocoa, you want to learn more about bindings or something, go to Cocoa Dev Central, and they provide tutorials.