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 may have transcription errors.

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 Derek 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 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 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 the 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 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 HIVs 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, we use NSViews, which are really very similar to HIViews. Cocoa applications are also bundled and also shouldn't 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. And we access files and the resource forks 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 Metrowerks 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. Used to work at Metrowerks. But when I read this, this really means a lot. I mean, here we have a longtime Carbon, Power Plant, and Metrowerks 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, string-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 announce 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 Power Plant.

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 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 in 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. 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 NSCursor directly.

So, Cocoa Design. As you know, Cocoa's 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 RegistrationController. 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's 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 at Apple 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.

Cocoa can easily interact with other subsystems like Carbon, BSD, and Quartz. And 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 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 get control value and set control value. 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 set color 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 window's rectangle matches the previous window rectangle. Maybe then we'll call sizeWindow and return no error or coerce 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 and 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 getInfo, in this case, a getInfo on main.c. And we can coerce its file type to be sourceCode.c.objc. It's a great tip.

Next one, code sense. 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 note. 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/ 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. 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 waitNextEvent.

After you feel comfortable, you change waitNextEvent to run application event loop, and you're off. You can kind of adopt the same strategy when looking at Objective-C in 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 NSView 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 anytime 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 as 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 NS view within an HI view. 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 WebKit 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. And the next one is Carbon Cocoa Core Image Tab. So 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. We have the HIV view NS view. This sample is a leopard-only sample, and it shows how to embed an NS view in an HIV view. 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 CarbonCoco core image tab sample I was talking about. Go ahead and set this one up. Let me get something fun here.

OK, 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. It's 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.

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 at 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. Which one's the advanced? 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 Derek 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. None of us had really-- well, 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, you know, wallow in the mire with us. And if I inspire you to try Cocoa at home, then I'll have done my job admirably.

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++. A nice thing, though, 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'll 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. And 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, 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 spent 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 it looked 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, Derek, 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's 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 Quartz 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 Derek mentioned, it allows you to combine C++ and Objective-C in the same file, or often in the same line. If you wanna 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 Derek 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 as needing objective C++.

Now, that's not to say that everything with Objective C++ is rosy and bright. We did run into a couple of problems. The first one that's usually fairly obvious is that if you're sharing code with Windows, you don't necessarily want to have Objective C code in the middle of something that you're going to try and pass to Visual Studio. You can flag it a little bit with preprocessor macros, F0s, and that sort of thing. But it's something you want to try and avoid if you can get at all possible. Another thing to note about Objective C++, which may confuse some people, it's not a blending of Objective-C and C++. There is no sort of mixing of the object models.

By that, I mean you can't declare a C++ class and derive an Objective-C class off of it as a subclass. It's just peaceful coexistence of the two models within certain files. Another thing that sort of bit us there close to the end of the development cycle that's worth mentioning, you have to watch your propagation of exceptions carefully. As a general rule, I try and avoid propagating exceptions across boundary layers anyway, say from a library up to your main application. But it's more important when you're sending things from Objective-C++ to C++ and those sorts of things, because an Objective-C exception won't unwind the C++ stack the way you want it to. And a C++ exception, if it runs into something that is pure Objective-C, not Objective-C++, but pure Objective-C. That Objective-C code doesn't have, I guess it doesn't have the right stack frame information there, and actually the C++ exception will end up calling terminate and cancel out of your application. So we didn't have much Objective-C code in our application, but we found cases where we were trying to throw past system routines where the system made a call back to us and trying to propagate those exceptions caused problems. And we've reported them as bugs in radar. So just some miscellaneous facts about MindManager. When we created MindManager, we decided we wanted to be tiger only. We didn't try and support older version of the operating system. MindManager was developed entirely in Xcode. Our project is very big, and it's very complicated. So Xcode handled it famously. I'm glad that all of you are working on Xcode as well. Some things we found particularly useful was the build phases. Being able to do custom build phases that did shell scripts was also very handy. We used those to actually replace a lot of the functionality that would normally be handled by an installer by packaging things into our application bundle that we could, and it enabled us to do just a drag and drop install, which was really great for everyone concerned. Code completion, as Derek mentioned, it was very handy. Because we were Cocoa and working on Xcode, we were actually universal from a few hours after the keynote last year. So as soon as we could get our hands on the development tools and recompile our application, We were 99.9% of the way there. We did have to go in and do some in the zip code. There was code that was writing up binary headers. We had to deal with that. And AppleScript support, adding AppleScript support to the application through Objective-C was a whole lot easier than trying to use the object support library from the Carbon days. So if you get a chance and want to even implement Apple scripting inside of a Carbon application, you might look and see what it takes to bring in some of that for your help.

So let's talk about Cocoa itself. Cocoa contains some really great frameworks. And this plays into the idea that Derek kept mentioning, that it brings a lot of functionality together for you for free. The user experience for us came together very quickly. We didn't have to do a whole lot to 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 Derek 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 rerouted those menu items to our C++ code and went out from there. And as Derek 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 keep some of the same behaviors there. So rather than calling back out to, say, NS File Manager or NS File Handle 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 Quartz2D C 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 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 Derek already mentioned, the first thing is to realize that you already know a lot 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've put into user interface design, You might have to redo the nib file, but you don't have to relay out your controls 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 lifecycle, 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 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 sort of a whole new meaning in the Cocoa world. Derek mentioned the delegation instead of subclassing.

And 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. And I found places where I could take something I learned from the Cocoa side of things and apply it in the C++ code. So if you get really bogged down and, oh, I hate to have to learn this stuff, just realize that you're still learning. So 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 a 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. What you'll find is that 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 or something like that? So 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. And 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.

Once you get the basics under your belt, then it's time to learn the frameworks. And learning any framework takes time. It's true of every framework that I've ever had to work with. And I've done think class libraries and Mac app and power plant and MFC. And this is by far and away the largest part of learning Cocoa is getting used to the frameworks. Objective C is a minor bump along the road. You can get started inside your Carbon app, as Derek already mentioned. You can add a window that actually, the whole window is controlled by Cocoa. Get used to wiring things up in Interface Builder in the calls. But if you can't make that jump, then certainly adopting the modern Carbon techniques will help you get a little bit more familiar with that. Things like HIView and Core Foundation are a great way to start because they have very close analogs in the Cocoa world. All right. Naturally, you have to have the slide that reminds you to make use of the resources that are available to you. We make extensive use of the ADC reference library, looking up things in documentation. You have to read the headers in Cocoa just as you have to read them in Carbon. Lots of great documentation is actually stored in those headers. You can visit the Cocoa dev list, which is hosted at lists.apple.com. The Cocoa dev list is peopled with people of all experience levels in Cocoa, from brand-new beginners to people that have been doing it since the Next Step days. So there's lots of people that are willing to help you on those lists. Also, don't forget to read the release notes. Every time I read one of the Cocoa release notes, I find something new and exciting that I didn't know. But also, reading the release notes is valuable for another reason. Sometimes the release notes will document something that the documentation hasn't quite caught up with yet. So if there's some bit of functionality that you run into, you find a header file for it, you're not sure where it comes from, you don't find it in the documentation, try looking in the release notes and see if it's there.

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 Derek to help you wrap it up. All right. Thanks, Scott. Thank you.

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.