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

WWDC07 • Session 300

Development Tools State of the Union

Developer Tools • 1:15:26

Apple's development tools for Mac OS X Leopard bring sweeping advances in productivity, performance, and debugging capabilities. Get an overview of the new releases of Xcode and Interface Builder, the brand-new Xray and Dashcode tools, and more. Key members of the engineering team will demonstrate the new features, and give insight into the latest developer technologies.

Speakers: Andreas Wendker, Chris Espinosa, Dave Payne, Matt Firlik, Francois Jouaux, Todd Fernandez

Unlisted on Apple Developer site

Transcript

This transcript has potential transcription errors. We are working on an improved version.

Good afternoon and welcome to the Developer Tools State of the Union.

( Period of silence )

Mac users have high standards. They want you to amaze them, with cool applications. They want to use truly outstanding software. And of course great things don't just happen by themselves. But they do happen a lot faster if you apply the right tools. And that's what this session is about. You want to build fantastic applications. And we build the tools to help you with that. We build the tools that keep you productive and creative.

Together, with Xcode 2.0 on top of Tiger, we just finished the transition to Universal Intel and PowerPC applications. And now with Leopard and the next generation of the tools, we're going to take the lead that will take us to 64-bit binaries to graphically stunning user interfaces on top of frameworks like Core Animation. And to garbage collected Cobalt Objective-C apps.

This Leopard tools release to us engineers here at Apple is really exciting. A few years ago the when the inter transition was about to happen, they started putting a lot of energy into our tools. And of course, since the most important goal was to allow for easy transition of all your applications, we funneled almost all the energy into the transition.

It took a lot of work but it did pay off and that is behind us. If we can take that same energy and momentum and push out in new directions that are a lot of more innovative, and to really advance the state of developer tools. So in Leopard we've prepared a release for you that is a great mix of improvements to the base functionality, performance enhancements, commonly requested features and features that are based on completely new ideas.

Like every release of Mac OS X, Leopard will contain a lot of developer tools, some big and some small. We won't have the time to cover them all today in this session. But I do want to give you an impression for the most important improvements and additions that we implemented. And to do that, we're going to structure the session to four parts.

( Period of silence )

We're going to start out by taking a look at what we have in our toolbox for the Mac developers. Those of you that develop native Mac applications. Then you're going to take a look at the growing number of Mac developers that leverage software from other communities, like UNIX, Open Source or Scientific Computing.

Next we're going to take a look at the needs of the automation solution providers. Those of you that combine multiple applications into custom solutions. And last but not least, we are going to take a look at how it can help the thousands of developers that develop widgets for Mac OS X.

( Period of silence )

So this is our agenda, let's dive right in. Let's start with the Mac developers.

( Period of silence )

Native applications, all right, the center of the Mac user experience. Native applications are the ones that make use of the unique features that Mac OS X has to offer. And whether you work in one of the large companies or one of the major application suites or whether you work in a small shop in one of the more specialized Mac applications, you want to build tools for you that work great for all of you. And so we commonly ask for your feedback and this is what you tell us. You want tools that are fast, so fast they don't interrupt your work flow.

( Period of silence )

You want tools that scale to even the largest projects out there. You want tools that are tightly integrated with the Mac OS X platform and the underlying hardware and know how to make best use of it. And maybe most importantly, you want tools that quickly unlock new features in Mac OS X to you and thus foster your innovation.

The tools that most of you need of most Mac applications developers use are of course Xcode, our universal IDE, and Interface Builder, our user interface design tool. And in Leopard we are shipping major new revisions of both these applications. Both applications have dramatically improved workflows and new features that allow you to be even more creative. And to explain that a little bit, I'd like to read a quote to you. It's from a book that inspired us while we were working on this release. It's from, never mind.

( Laughter )

But here's how it goes.

"What makes experience generally satisfying is a state of consciousness called flow a state of concentration so focused that it amounts to absolute absorption in an activity." The new workflow is an excellent interface builder. in precisely at keeping you in such a state of flow. And to show you I'd like to ask Chris Espinosa to come up on stage and give you the first demo.

( Applause ) >> Thank you Andreas. The two key elements of the flow of Xcode 3.0 and Interface Builder 3.0 are that we're bringing information to you where you are and then we're moving the tools out of the way. And I'm going to show you that by doing some simple development steps in a little application I like called Grand Perspective. Grand Perspective looks at my disk and gives me a tree view of everything on my disk.

I can drill down in it to see the sizes and names of the individual files in the directories of pop back up. Now what I'm going to do with Grand Perspective is something I've always wanted to in it, which is to add some menu items to go down and up and put command keys on there so I can go down and up with the keyboard. Fairly simple step.

So the first thing I'm going to do is go over to my Grand Perspective project. Now I've started doing this already, and so I've got a couple of things wired up, but I'm not quite finished yet. So I will go open up the main menu code file for my recent files menu.

And I can see this is the state of the program where I left it off. Now notice, I'm just seeing a top level overview of my code. That's because I folded all the methods and even all of the comments out of the way. I'm moving things out of the way so I can focus on my work.

Down here, I see this not quite finished up action method, which is where I've been working. And what I want to do is compile to see how well it's going so far. Well I compile and I get a compiler error. But the compiler error doesn't pop up in a second window covering my work, it pops up as a message bubble right in line in my text telling me exactly what's wrong.

And I can see that it's, I can hide it or show it again if I want. And I can see all messages at a time. I see that it says I've got a syntax error before my semicolon. I just fix it, recompile and now that the error is gone, the message bubble is gone. We bring the information to you.

Now the second thing I need to do is I need to create the menu item for the up, the up control. And to do that I need to go to the nib. Now I don't know where that nib is and I don't want to go, have to go back to my project window to find it. But I know the nib is in the class I'm working in, the main menu control.

I command double click on main menu control and it shows me where the class is defined in the nib, not just in the source code. We have the information of where everything is defined in the nibs. We bring that information to you rather than making you go look for it.

( Applause )

Now you can see, this is new Interface Builder 3.0. It has a really refreshed graphic look. It's got a not, lot of new Interface Builder elements. It's got a really refined work flow. And one of the things is the new library that replaces the palettes. I've got, I can go quickly to all of my menu, menu related items in my Interface Builder. And I see for example, this menu item right here, pick it up, drag it right in.

( Period of silence )

Move up.

( Period of silence )

Add the command key. And I've created my item. Now I need to wire it to that class, that class I navigated directly to. I just go to the main menu control, and I bring up a connection panel.

And the connection panel shows me all of the connections from that class to that nib. And I see down at the bottom, the up action is unconnected. So I just grab this connection, and I'll drag it to that item. And notice Interface Builder moves the connection panel out of the way to let me make the connection. When I close it and save it.

( Period of silence )

Then I can go back here and I can build and run my application and Grand Perspective is running and I have my move up command. Now usually I don't run code that I've never debugged before. So I want to go in and set a break point in this application so I step through that code that I just wrote.

But notice I build and ran it, I didn't start it under the debugger. If I want to set a break point, do I have to quit the application and go back? No. I just click the break points there, Xcode automatically attaches the debugger to the running application when you set the break point and now it's running under the debugger.

( Applause )

So that when I, so that when I drill down and move up, I hit my break point. Now notice, I'm not in a debugger window. I'm still in my source code at exactly the point where I was editing. But notice also there are some new things up here.

Here's my back trace, my stack trace of where I am. Here's my list of threads. And here are my simple debugger controls to step into code right here in my source code window. So I don't have to go to a separate window to debug, I can debug right in my source. Now one of the debug window has is all of my variables. Well, how do I get those? I just hover over this item, and I see the value of that variable right here in my source without having to go elsewhere. Now this is an Objective-C class.

I see the class pointer doesn't do very much for me. But I can see all the I vars like that. I can even see that this object which is the tree map, has a top level array and I can see the contents of that array. You can see NS arrays, CF arrays, C arrays and even STL vectors right in the tool kit, right in your source code.

( Applause )

And the data tips as we call them aren't just for seeing data. You can also change data as well. If I step over this line of code and get to this one, I want to test for robustness and see how visible root tree index works. So I can just go in here and if I set this to a different value, I can continue straight from here and I can even set the value of variables in the debugger.

So now you can see I've wired up that menu item and it works. But one of the things we notice is when I'm at the top of the tree, even when the up menu, the up button is dimmed, the up item is still enabled. I have a little more work to do. So let me go back here. I'll remove my other break point. Fold up my code and move up my validate menu item method.

Now I can see that this method is a little difficult to read because the authors use indentation not just to show the braces in the if statements, but also to show the parallelism of the clauses in the if statements. Then the indentation gets a little screwy. So I can set my insertion point and turn on code foldings focus follow selection.

And it shows me the scope of where the insertion point is. Gets successively grayer as I get successively further out of scope. Just really helps me focus on my work. As I move the insertion point, the focus follows the selection. And I can turn that on and off with command keys.

( Applause )

Now I can see that what I'm looking for is the handler for the up action selector. I'll set my break point here, go back. And when I touch the file menu that method should fire and the break point should hit. And there I am. Well, this doesn't help very much.

I'm in a return statement. How do I figure out what the return value of the statement is going to be? I can't see that anywhere. Well what I can do is just double click this brace and a little information button pops up. I click it and it evaluates the expression.

( Applause )

This shows me that the return value is going to be one, which is why its, why it's enabled at this point. And I want it to be disabled. Well, I can see by inspection, what I did was I just copied and pasted the line from the previous method, so I'll change this from down to up.

And evaluate that, just to kind of test fly it to see whether that's what I want. Click it, it evaluates it, I see the value is zero and that's what I want. So now I can continue.

( Period of silence )

Quit the application, go back here.

( Period of silence )

And then I can build and go and notice it remembered I was in debug mode, so when I build and go, it goes back into debug mode.

( Period of silence )

And I'm building and running again.

Now one of the things that's going to happen is when I test this code, if I hit the break point, I'm going to hit it, but it swaps Xcode to the front. And when I continue through, the menu is going to have been rolled up so I can't verify my work. I want Xcode to get out of my way.

So what I'm going to do is I'm going to turn on our mini debugger. And the mini debugger is a little floating window that floats on top of the front most application. So I can go back here, even make it full screen, it's great for debugging full screen applications. And when I hit, it just expands it in place without swapping.

( Applause )

And when I continue, the menu pops down and I can see what I've done.

( Period of silence )

So now my work here with adding my menu items is done. But I want to do a little more clean up on this application before I'm finished. One of the things I like doing is to change the terminology of classes to more match my favorite terminology.

I, I like performance panel control to be preferences panel controller for example. But that kind of clean up can be error prone. You know, I don't know where all the places that this person used that in the application. And, and just general find and replace may not find all the places.

Well that's why we have refactoring in Xcode 3.0. I can select a preferences panel control name and I can click the refactor button. And it brings up a panel that lets me type a new name. This is one of the many refactorings available. I will choose to rename the related files.

( Period of silence )

And I'll make a preview. And it shows me all of the places in my code that it would need to make changes to have it semantically equivalent application. Not just in the names and the contents of the files that implement that class, but where the class is used and also even in the nib file where that class is connected to. And with one button, it makes all the changes at once so when I build and run, I have a semantically correct application where the preferences panel controller works correctly the first time.

Now this will lead me to do a lot of experimentation, a lot of innovation, and make a lot of changes maybe some of which I don't want to make. One of the ways that Xcode will help bring information to you is to bring your old versions of your software back to you when you need them, when you've been too innovative. And that's with our snapshot function. You notice all along I've been making snapshots of the program, as I've been changing it. I've taken a snapshot at every stage where I've changed something. And what I can do is for each version, I can see what files were changed.

And I can look at the changes on a file by file basis. And pick any version, and roll back to it at any time. So you can see with Xcode, we're really allowing you to not only focus on your work, to bring the information to you to get the tools out of your way, but also fostering experimentation and innovation to make your great applications Thank you very much.

( Applause )

Thank you Chris. So let's quickly the review that features of Xcode 3.0. We have a great new editor for you. It has dramatically better speed. It has improved in syntax coloring and code completion. We added code forwarding and code focus which highlights the block structure of your code and it's incredibly useful especially if you work with somebody else's code that you're unfamiliar with. Around this editor, we built a lot of workflows to bring the right information to the center of your attention instead of forcing you to switch the window.

Message bubbles will display information about bit errors and warnings as break point states and conditions right embedded in your source code. And while the debugging, the debugger button shows that at the top of the window, we give you access to the most common debugger controls. And data tips allow you to view and edit the, the values of variables while debugging. We've also made dropping in and out of the debugger much more seamless. Xcode will simply do the right thing based on the state of your break points and attach the debugger whenever necessary.

( Period of silence )

And the mini debugger is great because it stays tiny and out of your way until you really need it and because it hovers on top of your applications, so it works great for debugging full screen applications or games And if you want help with making some large structure changes to your source code, you can use our new refactoring feature. The factoring uses the indexing information that you collect about your project and it offers you set of operations that you can selectively apply to your source code.

You can choose from things like renaming classes and methods or moving them up and down in the class hierarchy or extracting new ones or applying the new Objective-C 2.0 syntax to it. What's great about our implementation of refactoring is is that it applies to all types of files in your project. While refactoring you can keep nib files data modifiers and sources in sync with each other.

( Period of silence )

Now refactoring can be quite invasive changes to your projects. But it's still very safe. In fact, much safer than making all the changes by hand. First of all, you can preview all the changes that we are suggesting in the dialogue that is based on finders. So you can see all available diffs.

And before applying any changes, you will take a snapshot. You will archive really the entire state of your project in a snapshot. So snapshotting pretty much gives you a project wide undo mechanism. And if you go and change your mind and you want to try another refactoring operation, you can simply revert back to the previous state with a click of a button.

( Period of silence )

Let's also look at Interface Builder. Interface Builder has a fresh new workflow, starting with a redesigned document window which now supports searching capabilities. The new Inspector supports the number one feature request editing of multiple objects at the same time.

( Applause )

The new library window is a flexible and efficient way to organize and find the objects that you want to add to your nib files. And in the spirit of flow, the connection panel bring connection information right to the center of your objects.

( Period of silence )

The Inspector has a new section that allows you to define, to set core animation for graphics properties. So you can now define graphically interesting user interface and animations right in Interface Builder. And Xcode and Interface Builder have been much more tightly integrated than before. They're now automatically sync class information. So if you go into your code and you add methods and variables, they automatically show up as actions and outlets in Interface Builder.

( Applause )

So that will give you pretty good idea of what's going on in the tools. But of course on the Mac the tools are just one part of what makes the platform such a great place for developers. Underneath the tools there are powerful programming languages, frameworks and of course the advancement hardware platform. And many of the prime advantages of the Mac development environment come from the tight integration of all these different layers.

Interface Builder is, is a fine example for an application that is powerful because the needs of the tools have been designed right into the underlying Cocoa frameworks. The previous session already have the different layers quite extensively, so I'm not going to repeat all of that to you. But I do want to point out a few highlights. I want to start with Objective-C.

( Period of silence )

On the Mac we of course support many program languages. But our language of choice is Objective-C. Objective-C really is the engine that powers Mac OS X. Objective-C and the underlying Cocoa frameworks were one of the big reasons why we were able to move so quickly from PowerPC to Intel.

And then one of the reasons why you can now move quickly from 32 to 64 bit. 2 And in Leopard we are taking Objective-C to the next level by adding a lot of great features for you. The most important one of course being garbage collection. It's implemented in opt-in fashion. So you can decide to adopt it at your own pace. But since it has made memory management so much simpler, and your applications more reliable, we do recommend that you consider using garbage collection for your next project.

( Period of silence )

In addition to garbage collection, Objective-C 2.0 has a variety of features that will make you write less code, and at the same time faster code. The most noteworthy features are the fast loop enumerators properties for which we also added a new convenient dot syntax, option methods and protocols. And in the 64-bit version of the run time, you also get a unified exception order of the C++ and non-fragile instance variables which allows you to make changes to the definition of your class without breaking any client code.

Now knowledge about all these features in Objective-C 2.0 is already built into the tools. The tools are ready for you to use with Objective-C 2.0. We've updated Xcode, the editor, the syntax carrier and code completion. We've updated Interface Builder and the core data modeling tools. Even give you performance tools that allow you to get a better understanding for how your applications behave in a garbage collection.

( Period of silence )

On the hardware side, everyone is pressing aggressively ahead with bring 64-bit capable multicore processors to the desktop environment. It was just last year that we shipped the first four core systems. And this year we are already shipping eight core systems. And in fact, if you look at the new hardware that we ship today, almost all of it is 64-bit capable and there's not a single piece of new Mac hardware that we ship that is not a multicore processor system.

So the time for you to get the applications ready for 64-bit address spaces and highly paralel execution models is now. It's really important that you use the Leopard tools now to prepare your applications for the next generation of processors. For Xcode, we've already done that work. I'm proud to tell you that Xcode runs in 64-bit and garbage collected and has a build system that has been cued extensively for many processor cores. Let's take a look at how the last point worked out for us.

( Period of silence )

This graph shows you build times on a Mac Pro by a number of processor cores. As you can see, we've dramatically improved both the speed and the scalability of our new build system. In fact, on the latest eight core systems building on Leopard with Xcode 3.0 is about twice as fast than building with Tiger and Xcode 2.4, twice as fast.

And those are just subtle improvements. Let's take advances in hardware into consideration as well. This graph shows you how build time decreased over the last year on the latest and greatest Mac hardware. As you can see, since 2003, we have decreased build time by a factor of 14. Now that's through a combination of both hardware and software improvements.

So optimizing for multiple processor cores has been big time, has paid off big time for us in Xcode. And I can't stress often enough how important it is that you do the same in your own applications. You might wonder how you can get some help with that. Well in Leopard, we are also taking a major step forward with our performance tool strategy.

Leopard will contain two major performance applications. There's going to be new version of Shark, our powerful profiling tool that many of you are already familiar with. And there's going to be a brand new application that's called Xray. Xray compliments Shark by looking at your application from a much higher level.

Essentially what Xray allows you to do is monitor, monitor the aspects. Monitor performance aspects of your applications, display them graphically in a timeline, visually correlate them and then drill into the events that stick out to you as performance problems. This is a screen shot of Xray. As you can see it looks a lot like GarageBand, uses the same metaphor of instruments and recordings in a timeline. One might even say Xray makes the applications rock.

( Laughter )

Xray gains a lot of its power through the use of DTrace, which is an Open Source technology that you integrate into Leopard.

( Applause )

It's a system-wide tracing mechanism that runs at the core of the OS and allows you to monitor the execution of any process in the system.

Essentially you can observe inputs, outputs and behaviors of funky parts and then analyze them with the help of synthesis scripting language. And we've integrated both DTrace and that scripting language right into Xray for you. And to show you, I'd like to ask Dave Payne to come up on stage and give you a demo of Xray.

( Applause )

Thank you Andreas. Okay. So I have a project I've been working on in Xcode that's a simple project and it has a list of groups and the members of those groups. Groups of people, members of those. And as a standard part of my development workflow, I also like to check the performance and behavioral characteristics of my application. Xcode makes that easy to do directly from the run menu with the start with performance tool sub menu.

Here we list various performance tools and various templates for Xray. You can also define your own templates for Xray and they would show up here also. So I'm going to go ahead and choose the object allocations template. So Xcode launches Xray. Xray goes ahead and launches my group viewer target application. I'll go ahead and bring up a document in group viewer.

Hmm. That lovely spinning wheel. Now we see in the graph of the object alloc instrument, memory growth over time as my, I'm exercising my application. And as I close the window, all the memory will be released and I'll get, or not. Okay, well maybe we have a problem here that we need to take a look at.

( Period of silence )

So I can click in the inspection bar and scrub through with the inspection head and actually see how much memory is allocated in my application over time. And might be a little hard to read here, but that's almost 40 megabytes of memory still remaining after I closed my document window. That's fairly excessive when we started out much, much smaller than that.

How can I take a look at what that memory is? Well down at the bottom at the detail view for object alloc, I can sort by various columns, one of the most useful ones is to sort by the net number of bytes. How many bytes do we have at the end of our run compared to at the start? So we see this for all allocations and also for various different categories of types and sizes of allocations. By far the largest category is the top one here.

And in fact if I click on the check box, let's go ahead and expand this a bit. So we can see this in more detail.

( Period of silence )

So now we see a red line on the graph that represents the, that top category of allocation type and its growth over time and the fact that it didn't go away when we closed the window.

So I can go in and take a look at all the specific allocations that we have there. Click on any particular one of those and bring up the extended detail view on the right. Now by skipping down through the framework code, I can get down to a stack frame from my application itself. When I double click on that, it takes me directly back to the line of code in Xcode where we allocated the NS image.

( Applause )

And in fact we very conveniently told ourselves that we left a leak in there.

So we allocated an NS image and set and I Var to that, but we didn't release the group image file here in the dealloc method. So I can go ahead and enter that in using Xocde's excellent new inline code completion. Makes it very easy for me to type this on stage. Go ahead and hit build and go. And again Xcode remembers the way I last launched my application so it brings it right back up in, in Xray again. Open up the documents.

Huh, again though that delay. But let's go ahead and scroll through the list of groups. Now we see the red line staying down at the bottom as we are deallocating those images as we brought them in. Close the window now. Ah, excellent, memory swiftly goes right back down to where it should be. So for demo purposes I'm going to close this document in Xray. And go ahead and bring up a new document. So I'd like to take a look at what was going on with that delay at the start of the application.

So again I'd like to use the object alloc template. But in addition, click to bring up the library of instruments in Xray. Here we see a wide variety of different aspects of the behavior of the application that we can consider. I'd like to drag in the reads and writes instrument.

And go ahead and close the library again. Now if you had used DTrace, you can customize your own instruments there. And get more in your library. So I'll go ahead and launch the executable. This is running exactly the same way as it was the last time around. But now we're going to be capturing two types of information, both the memory allocations and the read/write behavior of the application.

So now we see as the window is opening, we seem to have a lot of reads and writes going on. And just for kicks here, I'll scroll down through the list of members and see that in this case we have no activity here. And go ahead and quit out of group viewer again.

So again with the inspection hat I can scrub through and take a look and see that we've got a lot of read and write activity that coming from SQL Light. So my group viewer application is based on core data. And it's using SQL Light in the background. In this case, we tried to be smart.

And prematurely optimize our application, give the users a great user experience. So gee, we'll preload all our data upfront so that it's nice and fast when the user needs it, right? Well, now that the customers are using larger documents, the scalability of our application isn't working out very well.

So this is something for you to consider as well. Your app may work great but what happens when you throw a document that's a hundred times larger at it? So in fact as we scrub through here, we can see that we've got thousands of read and write calls going on. In fact, over 10,000 of them.

So this gives me an opportunity to change my application to fix that. I'll go into the document. Now the window for the document is backed by a core data array controller. For Leopard, we've added a new feature to the core data controllers that allows me to turn on lazy fetching.

So in this case, save and build. And I'll just go ahead and run the document, the target application again. This gives me a new run in Xray. So hides what was there before, gives me a new run. I can go ahead and bring up the target document again. Now we see that it was instantaneous in bringing this up. And as I scroll through the list of members, now I do have some disk activity as I bring new members in. So that appears to be giving a much better user experience.

And in fact if we scrub through we can see that in this case, remember before we had over 10,000 reads and writes. Here we have less than 300 in this case. In fact, by closing the detail view and bringing up the Inspector for the reads and writes instrument, first off I can zoom in on that.

And also do show all runs. So I can see on the bottom the initial run that I had done with all the disk activity upfront and then the improved run on the top. And by going into the object alloc instrument, I can also show all runs on it. And see that in fact I've got a second benefit out of doing the lazy fetching in that I've vastly reduced the amount of memory that I'm using.

So we can see that I'm correlating different types of performance data for my application. So we're really excited about the possibilities with Xray and DTrace. And we look forward to seeing what you can do with them to really improve the performance and scalability of your applications and just amaze us.

Thank you.

( Applause )

Thank you Dave. Xray. The basic workflow of Xray is similar to many of our other tools. It's a document based application where each document represents a trace scenario. And you use like in Interface Builder, a live read window to manage the instruments that you want to add to your documents.

( Period of silence )

Out of the box, Xray has a set of about 15 instruments that allow you to monitor the different aspects of the system ranging from CPU usage, memory, fire activity, I/O graphics, etcetera. But you aren't limited to this set of instruments. Because of DTrace and the DTrace based instrument builder that we have in Xray, you can actually define your own instruments. And that of course allows you to turn this library into your own much larger custom library.

Define your own instruments allows you to take Xray into directions that we haven't foreseen yet.

( Period of silence )

Let's take a look at the document window again. As you already saw is based on timeline. If you run the same scenario multiple times, you can look at the different runs side by side in the window.

And once you're done collecting all the data that you want to analyze, Xray has great data mining tools. You can zoom in on smaller ranges of time to fade out unnecessary data. You can bring up detailed views to look at individual measurements and stack traces.

( Period of silence )

To set up repetitive test scenarios, you can use UI recording feature in Xray. UI recording allows you to record the scenario in the application you're monitoring, user interface events to record user interface events and then replay them several times from within Xray.

So you can study how the behavior of the application changes if you make changes to your code.

( Period of silence )

And Xray allows you to save documents as templates. And that gives you a nice integration into Xcode. You can invoke those templates right from within Xcode, right after building and immediately see the changes that your codes changes invoked.

( Period of silence )

So, as you can see, we took the tools for the native application developers a huge step forward in Leopard. You can simply flow from one task to the other in Xcode and Interface Builder and continue right into Shark and Xray to work on performance like what user performance, users obviously crave for performance. And going forward, that of course means that you should take a look at multi core processors that's going to be the most important way for you to get performance out of your applications. So with that, let's go on to the community developers.

( Period of silence )

There are many communities that UNIX, Open Source, Scientific Computing or Web that explore new technologies. Often those communities are not tied to the Mac ecosystem, but they use the Mac because they find it's the most desirable place to do that kind of exploration. It's the platform that keeps them most productive.

Of course when working on such a project, it often feels much more like being a passenger on the train instead of the driver in your own car. Because you don't control the entire technology stack. Often you bring in cross platform projects that are not designed or not, they are not prepared to work with Xcode directly.

So the needs of the community developers are quite a bit different from the needs of the native application developers. Most importantly, they need lightweight tools that don't impose any kind of restrictions on them. Specifically they need to be able to choose arbitrary build systems and arbitrary programming languages.

Unfortunately, most of the time the tools that are at your disposal are not designed to work together as developer tools. Many of you simply use finder, terminal and the text editor of your choice. So we thought you can do a lot better than that. And in effort to extending Xcode with a new feature that is specifically designed for the needs of the community developers. And we call it the Organizer. The Xcode Organizer allows you to leverage the strengths of Xcode without getting any restrictions. To show you, I'd like to ask Matt Firlik to come up on stage and give you another demo.

( Applause )

Thank you Andreas. Show of hands, how many of you guys use Open Source technologies or community oriented technologies? That's great. Typically when you're working with community oriented software, you have a large number of elements to deal with. You've got repositories, you've got build systems, you've got projects you've got languages, you've got all these things you need to put together. And the Xcode Organizer and a lot of these other features in Xcode 3.0 make this really easy. So let's take a look at how we do that.

Up here on the screen, you're going to see the Xcode Organizer, in the upper left. And it looks like a standard Xcode window. There's a toolbar at the top with some standard build controls. And there's a content view beneath it. And in this content view you can see I've, see I've dragged in two Xcode projects that I've used before. So if I want to work with one of these projects, all I need to do is go and click on one of the projects, double click on it, and up comes the Xcode project.

Close it, goes away. So very simply, it's an easy way to manage all of the projects you want to work with. So there's no more relying on the recent files menu and making it this big so you see them all, or putting aliases on your desktop or anything like that. you can easily just put the projects in your Organizer that you work with. and this works great for framework oriented technologies where you need to build a bunch of things that integrate into your project.

Even better, I can just select one of these and click the build button. And without even opening the project, it's going to go ahead and build it. So if I have frameworks for libraries that I need to use but I don't need to edit, I can go ahead and build them and get on with the rest of my work.

Now the Organizer actually works better when we have some more content, so I'm going to use one of the new Xcode features which is the SCM Repository browser. So I'm going to go into the SCM menu and bring up the repository browser. And here you see a window on the left hand side are a list of all the repositories that have code that I work with.

so I can select a repository and use the controls across the top to browse the repositories, take a look at content and check out the content I need. So in this case, I'm going to select my local repository, click projects, click check out and select the desktop and there's my projects. No more going to a separate app, no more going to terminal. It's all right there.

( Period of silence ) I can drag my project folder into the Organizer and then expand it. And we can see a list of projects beneath it. Now these two projects may look interesting if you look very closely, these are not Xcode projects. These are in fact projects built with Makefiles.

So what happens say if I were to select this first project and click and hold on the build button? The menu comes down and the menu item says make all. The Organizer has gone and introspected my project and found that there's a build system it knows about and put in the commands that I need. So whether you're using a Makefile project, an Auto Comp project, or an Ant project, the Organizer allows you to build it now seamlessly with the same workflow you would with an Xcode project.

( Applause )

I just clicked make all and it built really quickly because of our nice fancy new hardware. But here's the Makefile that it actually invoked. And so it built the application on my desktop here. I'll go and launch it. And this is a Ruby Cocoa application that plays Asteroids. Very, very simple. So I just built this game from the Organizer.

Now the Organizer provides a number of other integration points with a lot of the same Xcode features that you know and love. For example, if I wanted to go ahead and modify this game, let's say I want to make it a little more less 80s and more 90s let's say. I can go ahead and bring up say, standard, actually I need to select Xcode first and bring up the standard find panel. And I'll just type in game.

Hit return and it searches all the contents of my Organizer and I can double click on one to bring it up or I could say show me where this is the Organizer and it highlights the file. I can click on the little button here at the button here at the bottom and reveal the embedded editor. And now here's the standard Xcode editor with all the great features you guys know and love. Syntax highlighting, code completion. I can even use the function pop up at the top to see all the list of classes and all the list of methods that are in this.

So I can go ahead and pick one and instantly get into working with my code. But we've also made sure to integrate other features with the Organizer including Interface Builder. So if I were to go ahead and take the game.nib file here and just double click on it, it's going to open up in Interface Builder like you'd expect.

And this is the nib file. The interface is presented in a single view that's the looks here. Now I want to go ahead and add something interesting to this. let's say we're going to add a tool bar. I can bring up the library as you saw Chris do before. But I'm going to actually take use of a new feature in Interface Builder which is the ability to customize the content in the library.

I've prebuilt a toolbar that I wanted to use and I just dragged it back into the library. So now I can drag it out and drop it in my interface, and there's my toolbar. Here's the one I want to use. And I can edit this just the same way I do a regular toolbar in a running application. Drag widgets in, connect them up, get on with your application.

So I want to connect up two methods to these sliders. I can select the files owner in document window here and bring up the Inspector. Those of you who are close enough to read it, at the very top, you'll see under the action list, it says rubyrocks.rb. Interface Builder has talked back to Xcode and said, where's the game class? And Xcode said, it's in this file. And not only lists the file, but lists all the methods that are already in that file for me.

So if I want to add some new methods, I can just click the plus button here and I'll type in a method, we'll call this change rock size. and hit return. Now Interface Builder has always had the ability to generate source code for you for Objective-C, but it now includes the ability to generate source code for Ruby and for Python. So.

( Applause )

So I can go ahead and grab this and instead of generating entire source file, what I want to do is just make this a little more efficient. I'm going to grab it from the Inspector and just drag it into my source code. What do you think is going to happen when I let go? There's the method that I need to implement. So it's put it right in my source code. I can go ahead and use some completion here to get asteroid size as the instance variable I want to change. And I want to send it to the integer value of the slider.

Now while I'm already in the editor here, let's just go ahead and implement the other method that I want to create. And we'll call this change missile size, make sure to copy that down here. And the instance variable I want to change is called missile size. so I'll save that.

So now I have the new method that I want to connect up. And let's go back to Interface Builder to connect those. You'll note that when I go back to Interface Builder, the Inspector is updated with the method I just typed into my source code. No importing headers, no refreshing anything. It's gone back and found the method that I just created in the source code.

( Applause )

So I can go to the Inspector and or the connections Inspector and set up the missile size and set up the asteroid size, save my game. Let's go back to the Organizer and build the game again. And now when I bring up the asteroids game, now I have a technical advantage where if my aim is really, really poor, I can make the asteroids much bigger or if I want to do something more appropriate for like a 9 year old, I could just give myself bigger missiles and take over the universe.

( Laughter )

So, very quickly and very easily, see we can integrate different build systems and different languages with the Organizer and get you guys on the way with your projects.

( Applause )

Now the second project I want to show you is something called Square Charge. And this is actually a project built with the Intel Fortran compiler. So this is a project that I just wanted to put in here. And I'm taking advantage in this case of another integration feature, which if you look up, there are some extra files in this project called XC command files. Instead of modifying the project as it existed, I just want to augment it with information for the Organizer.

So for this project, if I go and select it, you'll note that now when I pull down the build window, build menu, it has a list of all the Make configurations. I went in to configure this before, so I can pick any one of them and have it built.

If I bring up the detail view, you can see this is invoking the Intel Fortran compiler. And just went and build it for me. But this becomes much more interesting when you consider the possibilities outside of building or outside of cleaning. So for example, I can go over to the action menu here and you can see that I built in standard SCM commands that I want to use for this project.

And I could augment this by selecting the edit action menu here. And we provide an interface for you to add as many scripts as you want and different kinds. I can type them in directly here. I can reference shell scripts that exist on the file system. I could even go ahead and add Automator actions. So I could pull down the menu here. Go into my home directory and grab a list of Automator actions and add those right to my script menu.

And I can select any one of them and change where the input comes from, if I wanted to have the output discarded or not, display the errors and alerts, any kind of thing like that. And I could start to make my project much, much richer. Now I'm told that this project, let me get this straight, calculates the electrostatic potential of a series of points due the uniform distribution of the square of the bounding rectangle.

I have no idea what that means.

( Laughter )

However, I was able to go through and create an Automator action called create analysis chart. When I select it, it's going to invoke the Fortran application, process the output, dynamically generate AppleScript based on the output, tell pages to create a chart of what my application looks like. So now, any time I want to figure out my electrostatic whosy what's it, it's a click away.

( Laughter )

( Applause )

So you can start to see the potential here. Different kinds of build systems, different kind of languages, unlimited possibilities with the scripting interface. So we think this is going to be a great tool for you guys to use. Thank you.

( Applause )

Thank you Matt.

( Applause )

Thank you Matt. So the Organizer, it's been around, a tree view, that you can use to bookmark your project folders and other files that you want quick access to. You can expand the window to show the embedded editor and that editor is of course the new Xcode editor that has code forwarding and code focus. And very important in this context, we added syntax coloring and code completion for common scripting languages like Ruby and Python.

( Period of silence )

But the real meat of the Organizer is the powerful scripting infrastructure that you built on top of it. you can define arbitrary shade scripts to build and run your applications or to perform any other action that comes to your mind. In addition to shade scripts, you can also use Automator actions and AppleScripts.

( Period of silence )

This combination of a tree view, file tree view and embedded editor and the scripting infrastructure gives you nice integrated experience.

And again this all without imposing, without actually imposing any, and that is all without exposing any kind of restrictions on you. Now just to make sure that I'm not confusing anybody here, the Organizer is not meant as a replacement for projects. It's meant as a lightweight and uncomplicated addition to make Xcode accessible to a new group of users.

If you work in a native application project, you should of course continue using projects and get the benefits of the fast build system and all the features that can aid in your building the project index, like refactoring. That said, the Organizer does have everything you need to build with arbitrary build systems, arbitrary program languages.

And it's not limited to the community project. Its also very, it's also very useful for Xcode projects, for native application projects. You can, you can get quick access to commonly used files and you can use the scripting infrastructure to run scripts across multiple projects at the same time.

( Period of silence )

So the strength of the Organizer will be its simplicity and its flexibility. And we hope that it will make it very attractive to the group of users that so far have not been able to benefit from the Xcode infrastructure. With that, let's go on to the automation, automation solution providers.

( Period of silence )

Automation solution providers fill at very critical need on the Mac. They use technologies like AppleScript to combine multiple applications together into custom solutions that automate business processes and production workflows. They of course need the support from all the application vendors out there. In the form of scripting dictionaries and Automator actions and they need a good tool. And that tool of course is Automator. Automator is a dedicated workflow building tool for both scripting professionals and end users.

And since we shipped it in Tiger, it has become a runaway success. Developers have, have literally created thousands of actions and made them available for download. Developers have really created a full ecosystem around the application. And now in Leopard, we're making Automator even easier to use and more powerful. And to give you a demo of that, I'd like to ask Francois Jouaux to come up on stage and give you another demo.

( Applause )

Let's have fun with Automator today. Automator turns applications and OS features into building blocks, actions that let you build all kinds of work flows. And with an OS that is packed with fun features like Leopard, t here is an entire universe of fun workflows waiting to be built.

Today I want to build in front of you a party registration workflow. My idea is that I will put my computer at my entrance door and guests coming into my party will sign in. A snapshot of them will be taken. And they will be able to see who has joined the party before them.

( Period of silence )

Demo machine? So when you start Automator you are greeted by the starting point panel. So starting point panel gives you some options to preconfigure your workflow. I think of it as a way to avoid the dreaded white doc, workflow document syndrome that I fear so much. And I will select the photos and images starting point and use my computer's camera here on iSight, as input.

( Period of silence )

That's it.

I have a very simple workflow. Let's save the picture taken in my snapshots folder which is also happens to be a stack on my desktop.

( Period of silence )

Now there are many, many actions available in Automator. And for me the easiest way to find the action I need is to use a search field.

The search field here will let me search for a feature that I want to apply to my action, to my picture taken. I type the first few letters of Quartz and I find a Quartz Composition feature. So there are many features available, but trust me I will look less creepy in sepia than anything else.

( Laughter )

Let's take this opportunity to show a few more fun actions available. For example, there is a, a new action to control a screensaver.

( Period of silence )

There is also a new action to perform loops. So this is actually very powerful. It lets me look over and over my workflow. It can take the output of the workflow as the input of the next run. It, you can decide how many times you want to run it or for how long. In that case, that trivial case, I will loop automatically and loop for the duration of my party.

( Period of silence )

That's it, I already have a quite functional workflow, but remember that I want some more user interaction. I want people to sign in. So I'm going to search this time for my, the next action by using the categories. And if I go to the text category, I see I can ask for text.

Which will pop up a panel, and the question is what's your name?

( Period of silence )

Now, hmm. I think here I need to keep the result of the, of this action in a variable. Well this is the biggest feature added to Automator in Leopard, support for variables. It is very simple to use variables in Leopard. Watch this. I select a field, right click, create a new variable.

( Period of silence )

This takes care of using the variable. Now how do I set its value? Well actions return results. And variables can take these results when you drag them just below the action as needed. It's a magical set value of variable action appears. That's it, my variable is entirely wired up.

( Applause )

Now variables are very useful, they are real time savers when you reuse them. And to illustrate this, I'm going to send myself a to do item to remind me to thank the person that just came to the party. And I can go to the calendar category of action.

Search, find a new to do item. And I will add it just before the screen saver action. See how I can mix plain text and variable to build the title of the to do item.

( Period of silence )

For this particular action, I need to remember to tell it to ignore its input.

( Period of silence )

Whoa.

( Laughter )

The party already started.

( Laughter )

( Applause )

Okay. there's another type of variable, a variable in Automator too. We call them smart variables. These are non customizable, they are preset by the computer, but they are not constant either. They will always be reevaluated as your workflow run depending on who is the current user on which machine it is run on. And in that case I would like to change the name of the picture taken.

( Period of silence )

And give it a month and a day. This way I will forever remember the date when Joe came in dressed as a penguin to my party. That's it. I have a complete workflow. It's ready to be run. But first I want to save it as a plug in and to save it as a plug in I just give it a name.

( Period of silence ) And hide Automator. It is now in my script menu bar, right up there.

( Period of silence )

No it's not.

( Laughter )

Let me bring it back up. Save as plug in. Oh yeah, I saved it in my script menu. Okay. All right.

My name is Francois.

( Period of silence )

- Tomi!

( Laughter )

- And the screen saver kicks in.

( Applause )

Looks like there are only geeks that showing to me at this party for now. Next person can come in, why don't you join us Andreas?

  • Ah, maybe later.
  • Let's party. So I'm sure you will have a lot of fun with the new features in Automator. Thank you.
  • Thank you Francois.

( Applause )

Automator. The most important new feature in Automator like Francois just mentioned is variables. You can use smart variables, set your computer by Automator, and give you access to common system and user properties. Or you can define your own variables which allows you to reuse input values multiple times within your workflow.

Like Xray, Automator supports UI recording. In Automator we call it Watch Me Do. You can use it to define your own custom actions, even for applications that don't support any actions yet. Indeed the Automator gets rounded up by a variety of smaller workflow improvements. Starting points make it a lot easier for you to create new workflows. The Run Log gives you a better overview of what's going on while you execute them. There's a new looping facility and of course there are many new actions that allow you to define new types of workflows.

Let's also take a look at of the technologies behind Automator Most importantly is of course AppleScript which has become even more powerful in Leopard with the addition of the Scripting Bridge.

( Period of silence )

With the Scripting Bridge developers who add support for SppleScript to their applications also get support for other programming languages for free. Essentially what happens is that if you take your application and you make it scriptable, it can be accessed through other programming languages like Objective-C, Ruby and Python through the Scripting Bridge. The scripting dictionary pretty much turns in an API that other developers can use.

( Applause )

So using Leopard means having a good time for the automation solution providers. The combination of the new Automator, AppleScript and the Scripting Bridge is a powerful punch to make it even more productive than ever before. And of course whenever there's a good time for the automation solution providers, there's also a good time for those of you that make your application scriptable. Adding script ability in our experiences saves additional software. And especially now with the Scripting Bridge, there's a huge community of people out there that want to use your applications. So it's definitely worth the smallest extra effort to add scriptability to your apps.

And with that, let's go on to widget development. As you already heard this morning, Leopard will contain a new tool that is focused solely on the creation of bridges. And it's called Dashcode. Dashcode is a complete widget development environment and after last year's WWDC we already made a public beta version of it available for download.

That beta was a huge success for us. We had nearly 50,000 downloadsP with a result that of the many thousands of widgets currently available on Apple's website for download, many of them have already been created with Dashcode.

( Period of silence )

This is what some of you had to say about it.

( Period of silence )

So as you can see, the feedback on Dashcode was overwhelmingly positive. You have sent in a lot of encouraging feedback. You have sent in a great amount of great suggestions and we have tried to incorporate as many of them as possible into the Leopard version of Dashcode.

And to show you, I'd like to ask Todd Fernandez to come up on stage and give you another demo. ( Applause ) >> Thank you Andreas, and good afternoon developers. We really do appreciate all of your feedback on our Dashcode Beta. As Andreas mentioned, we have incorporated your suggestions as well as a number of exciting new features into a great Dashcode release for Leopard.

There's been a lot of excitement in the web community about mashups. Combining all sorts of different types of information provided by RSS feeds with their geographical location with maps makes that information far more useful. So we've added a new maps template to Dashcode that makes it really easy and fun to take advantage of all those feeds. And I'd love to show it to you now. ( Period of silence ) Here's Dashcode's template chooser, I'm going to create my widget. And let's see.

Let's find a nice feed in Safari. This is, this is a Flickr feed that provides photos with particular tag. I thought Leopard would be particularly appropriate today. All we need to do is drag this feed into our widget and run it. And the widget will fetch all that information from the feed and lay out those pictures around the world on the map. And I can see the photos and get a nice full screen view. That's it. It's that easy.

( Applause )

But the power of Dashcode is really what, the power it gives you to go beyond the template and create customized widgets. And to do that I'm going to use Dashcode's library. Very similar to what you've already seen today in Xray and Interface Builder. I'm also going to switch to use a different feed.

One from our friends at the US Geological Service which provides information on recent earthquakes, which I hope will be completely irrelevant to us here in San Francisco this week. So let me bring up Dashcode's library, which provides me with three different types of content that I can use to customize my widget. The first I'm going to use is some art from my iPhoto library.

And I can just drag it out to my widget and use Dashcode's guides to line it up. All right, that's great. I have customized the look of my widget but I also want to customize its functionality. I'd like to add a button to my widget that recenters the map on home. And to do that I'm going to use Dashcode's parts library.

Dozens of reusable parts of all sorts of different user interface elements that I can use to build my widget. And as I mentioned I'm going to use a button. So I can just drag that out of the library to my widget. And again use the guides to resize it.

Let's give it a name. All right, well, I've got my button there, but I need to give it some behavior. So I'm going to bring up the behaviors Inspector. And define a function for it to call when my user clicks that button. And when I make that connection, Dashcode opens up its integrated source editor and gives me a function prototype for that new function I've created. Keeping me in the flow of the task I'm trying to complete.

And that brings me to the third type of content in Dashcode's library, code snippets. Again, dozen of little pieces of code that you can use to build your widgets, common tasks that you use. And again, like in Interface Builder, you can drag your own snippets back to the library that you can use again and again as you build widgets.

And in fact, I've done that myself for this demo. I have the definition of this function as a snippet and I can just drag it right in there.

( Period of silence )

And there we go. So that's great. I've customized the look of my widget. I've customized its functionality, but I also want to give my widget's users the ability to customize the widget's behavior at run time.

So another great feature that the template provides is filtering of the information that the feed provides. It gives me for free, filtering on the title and description, common keys that are provided in the feeds and a couple of spare controls that I can wire up to other keys that of interest. Since we are looking at an earthquake feed, I thought we might be able to filter on the magnitude of the earthquakes.

All I need to do is provide the key. But how do I know what key is in the feed that represents the magnitude? This is actually a common problem for designing a widget that consumes any kind of RSS feed. How do I explore the feed and find out what's in it? Dashcode makes this really easy.

( Period of silence )

So I know this is an RSS feed that I'm consuming, but I haven't seen the code for this template before. How will I find where in the code this might be? Well I can use Dashcode's search field to search the entire project and see what I find.

And surely enough, there's a function parse RSS feed. That sounds promising. Let's look through here and see if I can find where it's parsing getting, get all item elements. That sounds like what I need. Let me set a break point and run, run the widget. Which will launch it under Dashcode's integrated JavaScript debugger.

There I've hit my break point. And as you can see, the graphical canvas view has been swapped out with my stack frame variable view. Again, keeping me in the flow. I can go ahead and step through my code. And as I step over lines of code, I can see that objects up in my stack frame and variable view get live data.

And I can see that this item class looks like what I need. But how am I going to find out what, what it has inside of it? Well, I'm going to use Dashcode's code evaluator. A live JavaScript console that allows me to interact with my running widget and execute arbitrary JavaScript code on it.

So I can use code completion here to explore this class, if I've never seen this code before. Although I'm going to skip a couple steps since I have seen it before. But you can imagine how I did this the first time. And find that that is in fact the magnitude that I'm looking for. All I need to do is find the key.

( Period of silence )

And I don't know why, but the author of this feed decided to call the magnitude subject. I'm not going to be particular, all I need to know is what it is. So I can stop my widget.

( Period of silence )

And get back to my source code because I need to disable that break point.

And all I need to do again is provide that key for my range filter feeds, right here in the attributes Inspector. So it was subject, right? Excellent, and I'm done. Let's go ahead and run the widget.

( Period of silence )

And again I see the widget laying out all the place marks for all the earthquakes.

( Period of silence )

I can click on my home button which takes me back home to California. And sure enough, there's plenty of earthquake activity there. I can flip over and filter on lets see if there are any larger earthquakes, magnitudes 6 to 7.

( Period of silence )

So we've just scratched the surface of the power of Dashcode to help you go beyond the template and create beautiful widgets that help promote your brand. And I hope that you love it, you have as much fun with it as we do. Thank you very much. Back to you Andreas.

( Applause )

So, Dashcode. It's comes with a great set of templates that allows you, that allow you to create fully functional widgets often in just a few clicks. And even if you're not an experienced JavaScript developer. But if you are, Dashcode has great editors for you. There's a graphical HTML/CSS editor, as well as an Xcode like JavaScript editor which of course has syntax coloring and code completion.

( Period of silence )

The library in Dashcode allow, gives you every thing you need to customize your widget. You can choose from a long list of predefined reusable JavaScript parts. You can choose from useful code snippets. And of course you get access to the folders in your media library.

But the most powerful feature of Dashcode is the debugger. It's a fully JavaScript debugger that you can set break points, break point conditions, you can monitor the state of variables while you execute your widget. You can even drop into the evaluator which allows you to interact with your running widget through full JavaScript expressions.

( Period of silence )

So Dashcode is really fun.

I actually can't tell you how many count on widgets three little daughters at home have already created with it. So if you haven't given it a try yet, please go take it out for a test ride. If you already have a native Mac application, please consider writing a widget that compliments your application. Users really love the quick status updates they can get through Dashboard widgets.

Now before I let you go and put all the cool news toys we showed you today to good use, let's talk about releases for a moment. Earlier today you received a Leopard DVD and that DVD of course contains all the tools I showed you in this session today. We are also working on an Xcode 2.0 based release for you.

Later day, there will be a download of the 2.5 beta available for download to you and it contains bug fix releases to the older tools. What's great about Xcode 2.5 is it not only runs on Tiger, but both on Tiger and Leopard. So if you have specific projects you can't bring forward to Xcode 3.0 right now, this can smooth your transition to Leopard a bit. And what's.

( Applause )

And what's even better than that, is that they are delivering on the promise from last year. And you can install and run both Xcode 2.5 and Xcode 3.0 side by side on Leopard.

( Applause )

So these are the new tools. They are ready for you to use. And they do their best to make sure you don't end up with this, but instead with a modern piece of software and users really love and embrace. So please go out, innovate, amaze us, thank you for coming today.