Configure player

Close

WWDC Index does not host video files

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

URL pattern

preview

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

$id
ID of session: wwdc2003-410
$eventId
ID of event: wwdc2003
$eventContentId
ID of session without event part: 410
$eventShortId
Shortened ID of event: wwdc03
$year
Year of session: 2003
$extension
Extension of original filename: mov
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: ...

WWDC03 • Session 410

Cocoa Update

Application Frameworks • 1:03:49

This session provides an overview of new features and changes introduced in the Cocoa frameworks. Some of the topics covered include new features in views, controls, standard panels, document architecture, and text, as well as Foundation-level features such as scripting and networking.

Speakers: Ali Ozer, Chris Parker

Unlisted on Apple Developer site

Transcript

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

How you doing folks? Thank you all for coming. All you guys in the back, move on up front. There's a lot of space back here. I can't really see you people too well. Thank you for coming to today's session 410 Cocoa Update. If, like me, you love Cocoa, you're going to see a lot of really great stuff in here that's going to make you love it even more. If you don't yet love Cocoa, you will after this session. We're going to talk about some really great additions to the frameworks and here to talk about them, Ali Ozer, manager of Cocoa frameworks.

Yes, so we are going to talk about Cocoa. Great stuff we've added to Cocoa. Let's see. As usual, you might have come to these Cocoa Update talks before, we're going to talk about the changes we made in the AppKit, the application framework, and Foundation framework. We're going to talk about new features, and we're going to talk about some of the significant API changes we've made.

We are not going to talk about bug fixes because we don't have time to go into all of that stuff, but we are going to cover the major stuff. And we will also provide plenty of pointers to other sessions because there's a lot of information being presented to you at this WWDC. So first, the AppKit update, which I will do.

Okay, so if you had come to Scott Forstall and Bertrand's talk, you probably, you heard about the Aqua changes that we made. They're mostly refinements. Scott showed some of them to you. There are changes in the look of windows, menus, tab views, boxes, etc. Our goal with the Aqua refinements we made is that it's all automatic adoption by your apps. The metrics are compatible and the APIs are compatible. So hopefully no changes for your apps. I will just show you Some of these changes, they're pretty subtle for the most part.

On the right side you have the old Aqua look, the Jaguar, and the new side, the stuff in Panther. I'm not sure if you can really see, but the window title bar is slightly different. If you run Panther, you'll probably notice them. The splitter bar now has a more sort of elegant dimple. The slider is more elegant. It's thinner knob there. The buttons actually look somewhat better.

Also, the tab view on the box in the bottom, the right and the left, you notice that the tab view on the boxes have changed significantly, and they are much better. You know, more elegant, fresher look. And you'll note that despite the big change there, the metrics are compatible. The insides should still fit your views just fine. So if not, you know, you run into problems, please report bugs on that.

Other changes we made in Aqua you might have already noticed if you're running Panther is there's smooth scrolling now. The parameters are still being fine-tuned, but basically allowing you to not lose context as you scroll through pages. Faster window and sheet animations, and also a distinct look for main, key, and inactive windows. If you don't know what this means, I'll just touch upon it during my demo in a few minutes.

SafePanel and OpenPanel have undergone a lot of changes. You might have used it already and noticed it. It's brand new look and feel, but again, compatible APIs. That's our goal. The main goal here with the Safe and OpenPanel is, one, not only provide more functionality to the user like list view and column view, but also provide the same user-centric model we are providing in Finder.

So that's the open panel. And this is the saved panel running as a sheet and text edit. Now you'll notice that in the bottom of this screenshot, there's an accessory view. Again, text edit didn't have to change at all to use the new saved panel. The accessory view just works. The saved panel just works. It just looks and feels considerably different.

We have added a new API to SafePanel OpenPanel, which is independent of actually the changes we made. Actually, the API is in OpenPanel. As you know, you could have a new folder button in the SafePanel, but sometimes there are cases where you want it in the OpenPanel as well, and we've allowed you to do that with this new API.

We've also deprecated these view tags that SafePanel had. I don't think anybody was using them anymore, but if you are using them heavily, depending on them, you might want to let us know. These were the tags that let you get to the various UI elements in the Open and SafePanel so you could fiddle with them. Typically, we recommend using accessory views to customize these panels. Mini Controls is another new feature in Panther. It's not automatic. If you want to use Mini Controls, you have to ask for them. They are smaller than small.

You'll see the regular, the small, and the mini all the way at the right side are your mini controls there. As we improve our miniaturization technology, we will be able to fit 38 million controls on Windows, like our G5, but right now we have the mini controls. Mini Controls use Lucida Grandin 9 as their system font. We have added a new method to NSFont to allow you to dynamically get that figure as opposed to hardwiring it into your apps.

So, we have that new control and if you were at Scott Forstall's section of the State of the Union, you heard about that switcher thing. That's that switcher thing you see in Finder which lets you switch between two, three, four, you know, different modes. It is available in Finder and Jaguar. You've seen it there. OpenSafePanel also uses it. It's a subclass of control and also available as a cell. Yesterday in one of the sessions, somebody was asking that they could not see this control in Interface Builder yet.

That's because it's not there yet as a public API in the seed. It will be there for the final one. One problem we're having with this control is that we just can't come up with a name. So, we'd like you to help name this new class. There's immense brain power in this room, so please send us your name ideas to [email protected].

The only requirement that started with NS and, you know, don't put your name in it or whatever, but so... So this is all for fun. Just send us your things. We're just going to see if there are some great ideas out there. We have a few ideas. We're not super happy with most of them. So we'll see. And Legal asked me to put this next slide up. You send us that name. That name is ours. You can't claim anything, et cetera, et cetera. And your name isn't the name of a product.

NS Adobe Photoshop is not a good name. So just send us your names in the next few days. Not now. Listen to me now. But after the session, you can do it. And we'll see what comes up. And, you know, if we use your name, we'll give you a big thank you. So we have new button styles. The disclosure triangle, which is something that's been missing, is now a button style on an S button. We also have a textured button.

Tina, there you go. We also have the textured button style, which is basically buttons that look appropriate for texture that is metal windows. So it's just another style of button to get that. We also added a circular slider. It's a separate slider type. It's the little things. So, you set the slider type and there's an enum for the slider type.

Most of the rest of the slider API ends up working. For instance, the bottom slider in that picture, I don't know if you can see it, but it has little tick marks and so on. So you can, you know, the slider still works, the slider is just circular.

Toolbar now has the concept of selectable toolbar items. Scott Forstall mentioned this in his talk. This is like in system preferences where toolbar items are not actions, but they denote states. Just like with other toolbar stuff, it's pretty easy to use. Your delegate normally declares what items should be on the toolbar.

It now also declares, if it wants, what items can be selectable with this method. And it returns an area of the selectable identifiers. And then everything else is managed by the toolbar for you. If you want, of course, you can explicitly change the selected item with these two calls, set selected item, or you can ask for it with selected item identifier. Pretty straightforward.

Talking about selections, one problem we had with focus rings, and now that as we implement focus rings more and more throughout the kit, is in some cases, automatic focus rings. This is often if you've enabled focus rings or keyboard navigation, or even if not, because we draw focus rings for you on text fields and table views and such, sometimes a focus ring just doesn't look right.

An example is this screenshot. I don't know if you can tell, but this table view is hitting the top edge of the window, and the focus ring ends up just overlapping the border of the window up there. Sometimes you have this case where the table is across the one side of the one edge of the window, and again, you don't want a focus ring drawn. In these cases, you can now disable the focus ring drawing from its default setting to none, and there will be other settings we add in the future.

An exterior is where you actually say, "I want an exterior always," for some reason. Default just means control, do the right thing with the focus ring. There are cases where a table view actually decides not to draw the focus ring if it knows it won't look good. But But it can't always tell, and that's why we give you this control.

TextField Cell now has API for placeholder strings. This is this new UI paradigm that appeared in the last year or two, where TextField has a default placeholder where you can tell what you're supposed to type, like last name, address, search, Google, I think in the Safari toolbar, and so on.

So you can now specify a placeholder string. You can even specify an attributed string if you wish, if you don't like the grade version but you want some other radically different thing. So you specify the placeholder. As soon as the user starts typing, it's replaced by what they're typing.

Jumping from text field to search field. Thank you. Search field is a new control. It's a subclass of text field. It's also available as a cell. It's basically that the search functionality, the UI for the search functionality that you see in Safari, Mail, Address Book, a bunch of other apps.

And it features the search button on the the left side You know earlier I screwed up my left and right, didn't I? Oh well. So it features a search button on the left side, the X button on the right side, and these are customizable and there's a recents list as well. Let's just talk about the API a bit.

You can customize the search or cancel buttons. If you want, you can have some other button up here instead of a magnifying glass or not appear at all. You can customize the search menu. That's the menu that appears beneath the, you know, when you bring down the menu. You provide a template which allows you to say where you want the recents item to go or what other items you want in there.

You can also customize the way recents are handled. You can either have us manage the recents for you, or you can specify what the recents are. And you can even have the search field save the recents automatically to preferences so that, you know, the user types stuff, the recents are automatically saved. You don't ever have to worry about it. And you do that using the autosave name stuff that you might be familiar with from NS Window or NS Table View. You just specify this autosave name, it's automatically saved to preferences for you.

You can also specify the maximum recents if the default, I think, 10 is too big, too small. ThugMod Search Panel. The app is not only provider of technology, it's also a client of technology because the font panel uses the search field, as you can see in the bottom.

The font panel has many other features. It's got improved collection management. If you've played with it, you've probably seen it. Better user interface overall. You can now have color support and favorites and the ability to search fonts, as I mentioned. In the demo, I will just show the font panel quickly and see some other of its features.

The font panel now has the ability to enable/disable elements of the UI. This is useful in some cases where you want the user to select a font, but for instance, you don't want them to specify the font size or the font face or the weight or whatever. For instance, the user should just specify Lucida, and you just need to know Lucida.

You don't need to know it's 10 point, 12 point. If the first responder implements this method called ValidModesForFontPanel and returns what fields it wants, the other fields will be disabled. By default, if this method isn't implemented, which is of course the default state for 10.2 apps and most other cases, the standard mode's mask is assumed.

From Font Panel to Font Manager, you've seen the collections, and again Scott touched upon that. There's API for managing the collections. The collections are identified by a name, and they represent a bunch of fonts. We have methods for add a collection, remove a collection, and also of course enumerate the collection by getting an array of collection names.

Fairly straightforward. You'll note that when you add a collection, it's global for the user. That means the collection applies to all of the user's applications. It appears in the font panels. For all apps. There's an option to make a collection per app. However, in the WWDC seed, that option is not working yet.

In addition to being able to manage the collections, you can manage the fonts in the collections by adding fonts to a collection, removing fonts from a collection, or enumerating the fonts in a collection. Now note here that I'm not talking in terms of NSFont, which is how we usually represent fonts in Cocoa, but I'm talking in terms of this font descriptor object, which is another new object.

And that's here. Font descriptor is a lightweight object. It basically lets you specify a font with as much detail as you want. For instance, you can specify that it's Helvetica Oblique 13, or you can just specify it's Helvetica. You can even specify it's 13, but maybe that's not very useful. It also allows you to specify colors and a bunch of other attributes.

And NSFont descriptor is a much lighter weight than a font. So if you have a collection with, say, 10,000 fonts in it, you don't have to enumerate all those NSFont instances. And it also lets you represent fonts partially, and that's why we added this class. Expect this to appear more in future APIs.

So, talk about fonts, the next obvious topic is text. And there are lots of changes in text. In session 427, Friday afternoon at 5, it's a great time, you can stay that extra hour, avoid traffic, it's good. Anyway, that session will cover these in detail. Now, I do want to give a quick demo of text just to whet your appetite about what some of the stuff Doug Davidson will talk about in that session. So, demo 3, I think? Yes.

Okay, so let's see. One thing I mentioned earlier was this distinction between main, key, and inactive. I just want to show you that first. As you can see, the left window now is active. This one is active. When you bring up a font panel, like so, it's a not modal panel. The question is, which window doesn't act on? Now, in this case, it's obvious because this window is still active and my typing goes to that window.

However, if you make the font window, key, by clicking on it or by typing a font number here, for instance, then you have two windows and you, especially on larger screens, you know, a lot of you are getting 17 inches or big cinema displays, you can't tell if windows are side by side which one is active. And that's the case in Jaguar. Here, what ends up happening is the title bar has a distinct look.

Now, for users who don't understand this, it probably won't get in the way, but for users to, which understand this, I think it's a nice touch which makes it possible to know that, you know, if these two windows, when you're in this state, you're going to know exactly what window it will apply to. So, that's the distinction, main key inactive state distinction. Now, talking about the font panel, here it is. There's a search field, as I mentioned.

This is a menu here. As you can see, the UI has been refined a bit. You can show preview that we had that before. You can bring up a typography panel, which we did not have in Jaguar. This typography panel is context-sensitive. It's based on the current font. In Cocoa right now, in the WWDC, this panel isn't hooked up. But what it lets you do is it lets you set up a bunch of font-specific parameters, so it's for advanced typography.

But note, again, in the WWDC, it's not hooked up, so it's not functional in Cocoa applications. Another feature you'll see here is that edit sizes is now a sheet rather than a separate modal state. And also, we have a way to bring up the font panel directly from the font panel, which is this Manage Fonts menu item down here.

So one thing I want to show you right now in the tech, one of the features we've added is the text completion stuff. We've added automatic completion. Some of you might have already seen this in other contexts. PB certainly provided this before, and there were some packages out there like Mike Ferris' package, which provided completion.

What you basically get is, as you're typing, if you type your default completion character, which is either F5 or Option Escape, or you can change it to be Escape if you want, as you hit that character, it basically provides all the words that can complete it. And in this case, you know, welcome happens to be the first word. That's good. So I can just continue typing.

I'll type WW, and, well, you know, it doesn't know about WWDC. So in this case, you just will type, you know, welcome. You'll type WWDC. Now, the good thing is, once you've done that, next time you try to type WWDC, it will appear. And because it does appear in the document and it's close by, it goes all the way to the top. So that's a good thing.

So, let me close this document. One other feature in the text system is here's a document that looks pretty plain, but the extension will probably give you a clue as to what it is. We don't have Word on this machine, and that is a Word document. If I were to say open and go to my desktop here, you'll notice that the Word document will appear here. It actually does open. So we've added support for Word documents.

One thing to note though is that Word is a very rich document format and Word has a lot of features. There are many features of Word that we don't yet do out of the box, such as tables and stuff. Those features are not going to work very well. So expect us to work with the more simple document types. And in cases where we don't have Word around, I think it's pretty useful.

The good thing is you can also actually save as a Word document. So I can try to save this. And when you do that, in this case, it will actually tell me that the saving will be lossy because I opened the Word document and it might have lost some features. The good thing is once you save from text-edit a Word document, you try to save again, it won't warn you anymore because it knows it's no longer lossy. But anyway, this is a feature we'll be improving, but the basic, pretty solid support is there as is.

Okay, so one thing that we've added to the text system is something we've been missing for a long time, and that's a standard find panel. Here it is. It looks somewhat like the text edit one from before. Text edit now is about 500 or 300 lines thinner. It's got some nice, you know, basic find options, and, you know, it's available in the text system by default when you create one in IB, so it's there for you.

One problem people had with the text system was the default ruler. People didn't quite understand what some of those fields were. In fact, they didn't understand what all of them were, maybe, except for maybe this one. And we cleaned this stuff a bit. So for spacing now, we have this, you can single or double, and, I mean, that's nice and simple, but not very powerful.

You can also, for instance, go ahead and specify other stuff, like you can make the line height one and a half, and you can specify paragraph spacing if you wish, let's say 30 pixels, and suddenly, you know, you get those options. So it's, it's a lot of fun. So it's a lot more, I think, straightforward and intuitive to set these parameters right now. Another menu we've added here is the styles menu, and let me just talk about that briefly.

For instance, let's say instead of this black here, I want this to be outlined. And by the way, Mac OS 9 fans, you can notice the outline font over there, which we didn't have in Jaguar as well. So let's say you really like this outline font and you want to use it elsewhere in your document.

Previously, what you could do was you could copy the style and you could select this and you could paste the style. And if you could use these command keys, they're very useful for quickly propagating a style throughout your document. One thing we've done now is if you really like the style you can go ahead and Add to your favorites.

And let's say we call this WBC. Headline. And you specify whether you want the font and the ruler as part of the style. So now I can come back here, down here for instance, and I can say, yep, I want that, WWDC headline slide. So this is not style sheets, but simple way to preserve the styles you use often. And again, it's just standard part of the text system. Okay, so I think that's all for the demo right now.

So there are many user features. We showed some of them. Word documents, find panel, dealing with styles, a better text ruler, background color, which I didn't show you, but it's in there. Text doesn't support it yet. Text completion, setting base, writing direction. That's also, we added support for this for buy-die writers.

And also, we have character styles like outlines, shadows, etc. Not all of them are exposed to the UI. We've also added many new text attributes. Again, Doug will probably talk about these in more detail, but there's, you know, strike through colors, stroke colors, shadow, obliqueness, expansion. You can specify, attach a cursor to a range of text.

You can attach a tooltip to a range of text. You can specify line heights, as I showed you. And paragraph spacing, you have a lot more control over. Other new features include a new public typesetter class, the ATS typesetter, which gives you a lot more power over the typesetting process, and a glyph generator class.

And additional changes include truncated text drawing. If you have code where you measure the text and then you go ahead and redraw it after cutting it, clipping it, whatever, using the truncated text drawing will be a big performance win because we do all that measurement for you and put the ellipses in the right place. There's also improved accessibility.

Thank you. The improved accessibility allows the assistive apps to get at the backing store of text and get much more information about them and also a bunch of performance improvements. For instance, string drawing is way faster now. Again, session 427, Friday afternoon. I mentioned shadows, and a shadow is now a new class. It lets you specify a drop shadow.

It's independent of the CTM, so the light source determines where the light, the system light source determines where the shadow is. So it's the value for a new text attribute. If you set the shadow attribute to an instance of an shadow, all text will be drawn with that shadow. Now, shadow is a generally useful class. You can set offset blur, and you can use it anywhere, just like NSColor or NSFont by just saying set. So, you know, that's pretty straightforward. And then any drawing you do in that graphics context will appear with a shadow.

So let's talk about views for a while now. Views in Jaguar, one complaint that came up in various forums, discussions, etc., this view-rect coalescing problem where a view would, whenever it got multiple rects invalidated, it would coalesce them into a bigger rect. And that would end up causing it to draw more than necessary. Let me give you a demo, a little example.

Here's your window. Let's say the user clicks that checkbox at the top. And let's say clicking that checkbox causes that text field in the bottom to be updated. If these two happen in the same, you know, event cycle, which they probably would, you Although these individual views are invalid themselves, the superview, the common ancestor for these two views, ends up getting an invalidation wreck that's this big, which of course ends up touching, redrawing almost everything in the view. And in some cases it's no big deal, it's a result of an event, but in other cases there's a performance that could be significant. So this is the problem that we're looking to solve.

So in Panther, views track invalidated areas, and we restrict the clipping to the areas that need drawing only. So if a rect has multiple rectangles, we actually set the clip areas so any drawing you do will actually only appear in those areas by default. And another important thing about this is that the drawRect method, which is how a view draws itself, is still the funnel point for drawing. We did not want apps to change.

to for this feature to be effective across the system. Now what I mean by drawRect is the funnel is that drawRect will not get called multiple times with multiple rects. Instead, drawRect will get called once with a rectangle that's the union just like before, so that behavior hasn't changed and maintains compatibility. Now you can go ahead and draw just that rectangle as you did before and the clipping will save you. There will be some gain in performance there.

However, if you're sophisticated, you can call this method, getRectsBeingDrawn, and count and get back a list and count of rects. You do this in your drawRect method and as a result of that, you can just draw those rectangles, you know, because those are the rectangles we actually want you to draw.

We've also given you a convenience method to determine whether a given rect intersects these rectangles. That allows you to quickly determine whether a rect you have should be drawn. We've also given you a way to override the default clipping behavior. Before I said that we clip for you, you know, the rectangles. If you want to change that for some reason, you'd have to be pretty sophisticated to want to do that. You can override that behavior, return no, and do your own thing. There might be reasons for this, but it's fairly advanced.

Now, here you're looking at this thinking, "Well, if I have to do this, then my view that doesn't do this is not going to take advantage of this whole process." Well, it turns out that most of the time, the performance hit we get from this isn't because a view internally isn't managing rects. It's because at the Windows content level, the views that have updated are being coalesced.

The one view that really needs to implement this is a view like the content view of your window or maybe a box that can include multiple views. So just by doing it there, which we've done in the app kit, we are seeing many benefits, a lot of benefits to this thing. But if you have a view that's fairly sophisticated, a graphic view with a lot of changing documents, maybe animations, you might want to go to the next step and implement this method and make it even faster.

Another feature we've added to view, which was being asked a lot recently, was the concept this view hiding business. You can basically tell a view it's hidden. Thank you. And it not only hides that view, but it hides all its sub-views, of course. And it also manages a lot of stuff like cursor recs, tooltip recs, tracking recs are disabled, OpenGL services are ordered out, and the responder chains are just automatically. You don't want to be tabbing through and ending up in the weeds, of course. And the API is very Cocoa-esque, meaning simple.

You say set hidden or is hidden, and that's it. And everything else is handled for you. We do have a third method, unfortunately, so it's 50% more complex than maybe it needs to be. You can ask a view whether it's hidden or whether it's hidden because a super view of that view is hidden. Because clearly, you know, if your super view was hidden, you get hidden, but it's an implicit hiding and you can ask whether the view is in that state.

Oh, before I move over, move on, I should mention some people have implemented set hidden and is hidden in their applications as a category, for instance. In general, we should work with those categories. However, there are cases where we were assuming the set hidden we called was our implementation, and we've cleaned those up. So we believe we've addressed the compatibility problems.

But if you have your own set hidden methods or is hidden methods, just make sure things are still working right. Of course, something that might be bad is if you had a set hidden method but didn't have an is hidden method. So we're calling, you know, our is hidden, but your set hidden, and that might be a little bizarre. So there is a potential compatibility issue there, but we have, you know, addressed the ones we've seen.

Now there's a lot more view discussion and graphics discussion this afternoon, session 413 in the 2D drawing techniques. From view to window, if you manage your window's internals like you have your own toolbar, whatever, or you want a sheet to come out from a custom place, you can now have a delegate method that allows a sheet to come up from anywhere you want. So there it is. You basically specify a rectangle where it should come out of. And we ignore the height of the rectangle for now because sheets are always coming down. So if you specify a small width, it will genie out of there and so on.

You can make it come out of, for instance, if you have your own toolbar under that toolbar. We also allow you to have a custom minimized dock icon image. This API used to be there for a long time. It was disabled due to compatibility, but we enabled it again. So if you don't like the dock's, you know, minimized dock icon image, you can provide your own.

And as Windows, tooltips in Windows used to be disabled for all Windows except the active window. We enabled them so that inactive Windows in your active app, the tooltips now work. They are disabled in inactive applications because we don't want tooltips to just jump up at you everywhere. But you can enable it for an inactive, you can enable it for the Windows inactive app by telling those Windows that they should have tooltips no matter what, and here's the way to do that.

It used to be you can convert frame recs or content recs back and forth at a factory method. So you can tell for this window style what's the conversion. We now let you do it at the window level, and that lets you take special circumstances of the window into account like toolbars and who knows, maybe other future changes.

But these are basically a little more per instance specific ways to do that. We've also added eight new methods that parallel similar frame methods, where you can set the max size, min size, et cetera of a window based on the content size of the window, not the frame size of the window. So these are basically parallel to the existing frame ones. They look great.

They're not implemented in your seed though, so for now this is all you get for that. From window to alert, we've added a new public class. If you use alert panels, you know that that's one of the significant piece of C APIs we have in the kit. We added this class to add some flexibility over the C APIs. Okay.

So you can now assign key equivalents to your buttons. You can assign custom return values. You can show a help button. You see one in the left side here. And you can, if you want, you can provide more than three buttons, and sometimes the situation calls for it. The API here is fairly straightforward. You init an NSAlert, and then you set parameters, message text, informative text, icon, whatever you want.

Then you run it just like you run other sheets or panels with either run model or begin sheet for model window. So that brings up a sheet. So pretty straightforward. The one other thing here is that if you have old C-based, you know, you're making the old C-based calls, and you want to just convert those in your NSAlert class, we've given you a convenience method that does it.

This convenience method, in addition to just doing that same old, you know, same function call in the style, with a method style, it also sets the return value so that they're compatible with the old return values. The old return values were sort of, I don't know, if anybody ever looked at it, they're like some minus ones. They were like one, zero, one, and they weren't, you know, the rightmost button, and it wasn't clear what it is, and I don't even remember what it is now.

The new values are a lot better. They're like the rightmost button, rightmost button plus one, plus two, et cetera. But this will set up the old return values, assuming you want to use it in the old way. So use this if you're transferring code from your C-based one to this one. Of course, C-based ones aren't deprecated.

It's just, you know, you might want to switch for some reason or another. I mentioned the help button. To get a help button to show in your NSAlert, you say set help anchor, and you provide the anchor that should be open when the help button is on. The help button is pressed. If you want more sophisticated handling, you would implement the delegate method, alert show help, and you will be called, and you can then decide to show help any way you want.

Of course, in doing that, you might want to use these new help manager methods we've added. Before it used to be that you could have--I think you could have help anchor in your info playlist and it was automatically dealt with, but you didn't have finer control. With these new help manager methods, you can specify the help anchor you want, the book you want, and you can even also--. Let's open the help pages by specifying query string that you get from the user, for instance, using find string in book. If you specify nil there for the book, it will search in all the books.

Now one other way you might provide help is rather than using Help Viewer, if you want, you might maybe have your own way of opening documents or opening a help application. In that case, you probably turn to NS Workspace and we've added some new methods to NS Workspace as well. One of them is the ability to launch an app by bundle identifier. So rather than name or path, you can now launch it with bundle identifier and let launch services decide which version, which app it corresponds to.

We've also provided some options here. These are options like Launch and Classic, Print, Launch and Quit, etc. There are a bunch of things like that, or Print and Quit. So you specify those options. You can specify an Apple event if you wanted some Apple event-level customization there. And you also get back a launch identifier, which can be used for various other purposes.

Currently, it's not. I don't think there's any APIs that take advantage of it, but in the future there might be to identify what launch event you're talking about. You can also now open multiple files at once. With the second method, you just specify an array of URLs and they're all opened. And that's rather than calling it one at a time. And we'll see the counterparts of that in a little bit.

You can also now discover an application with bundle ID, so if you do want to get a path to an application but not launch it necessarily, you use this. And we also now let you see the bundle identifier launched application. It's in the dictionary you get back when you get back an app launch notification. And there's that key for that.

We also now have sleep notifications. We have Will Sleep and Did Wake. We don't have the other two. These two are not implemented in the WWDC seed, but they do what you might expect them. Now, in the Will Sleep notification, you can actually take your time to do some stuff if you want. And the machine won't go to sleep until you're done. However, you can't count on that because there might be cases where the machine is going to emergency sleep.

The lid is closed, or the power is going out, or there's no battery. In those cases, you might not even get this notification, or if you do, it might still go to sleep halfway through this. So don't count on being able to do stuff in this notification. It's just a way to, if you did want to do something, this is the way to do it. Better than what you had before.

Okay, so earlier we talked about opening multiple files. This is the counterpart. You will get an open files call, which includes all the files that were opened. This is very useful for instance if the user double clicks on, you know, 30 JPEG documents in Finder. If you want to hear that they all came as one big clump, you would implement this method and get all of them. Before there were ways like you'd implement open file.

You'd get 30 open calls and you could check to see whether you were on the same event cycle to deduce that they were all being opened together. If these methods are implemented, they will supersede the old methods which is application open file colon. Now note that with multiple file requests coming in at the same time, the delegate has more responsibility for handling UI and error conditions. For instance, you know, one of the files might not open. The user might cancel the opening process in between, you know, when a panel comes up or such.

To enable you to do this, typically you'd handle this by sending an Apple event. We've added a method in this application that lets you just send a reply to open or print and you can specify what you want communicated and it's handled for you. So you don't have to do any special Apple event stuff. Now if you do want more sophisticated behavior, you can send Apple events directly using Apple event manager class. Here the success is implied, so you would typically use this if you just want to communicate cancel or failure.

So let's jump to menus. Mac OS 9, those of you who use Mac OS 9, you know that when you went to the control panel menu item in the Apple menu, you could select that menu item all the way to the sub menu and it would open up the control panel where you could choose what you wanted.

Cocoa didn't have that ability to assign those, a super menu to be a leaf target and now you can do that. You can just set the target and action on a menu item and it will work. We also added this support for dynamic menu items based on key equivalent. What I mean by this is you hold down alternate or option or shift and the menu title changes and something different happens.

The way you do that is you just specify certain menu items as being alternates of the first one and if we notice that they're alternates, we just collapse them into one menu item. Now if you run such a Nib file on Jaguar, the individual menu items will show as distinct items which is reasonable behavior, maybe not exactly but in Jaguar this feature doesn't exist, so it's better than nothing.

Another thing in menus, you can now have attributed menu titles. You can't put full attributed strings here, like a Word document, but you can specify the style and I think an embedded image. It's fairly limited. And color. And you can also have tooltips on menu items. And NSMany now is a delegate. After so many years, it finally got a delegate. We added this for lazily populating the menu.

There are some menus which take time to populate and you don't want to necessarily do it at app launch. So we have this delegate method, menu needs update, and you can go ahead and populate the menu when you get that. That will be sent to you when the menu is brought up. Thank you.

[Transcript missing]

Okay, and one other feature that I haven't heard talked about in the sessions I went to is customizable command keys. In system preferences, you can now specify command keys for arbitrary menu items, and they can be either global or they can be per app. And this works in Cocoa and Carbon apps, so it's across the system.

So, you know, you can specify what menu equivalents you want for whatever. And here you see, for instance, text that has somehow, you know, start speaking has been set to command option S, hide others has been set to command option H, so it works everywhere, and so on. So that's, that's a great feature. fairly useful.

NSBrowser. One thing NSBrowser didn't have before was continuous horizontal scrolling. It was, if you remember, it would just jump in discrete steps. It's now implemented and it's on by default. We now also have column resizing, which is what Finder had this in Jaguar. Column resizing by default is not on, so the browser behaves like it did before because there are enough compatibility issues that we did not want to, you know, introduce incompatibilities as a result of this.

You can change the column resizing type to one of three values. The no column resizing means the columns will never resize. Before, they would resize based on the width of the browser. Auto column resizing is the behavior we have today and user column resizing is where the user can resize them any way they want.

And of course, it would be good to provide persistence of these values so you don't have to worry about them. So just by setting an autosave name like we saw earlier, you can get the column widths to be saved automatically in preferences. You can also, if you want to do more sophisticated action as a result of column width size changes, you can implement this notification and basically do whatever you want.

TableView now has index set based selection management. We'll talk about index set in a few minutes. Chris Parker will go into that class. But instead of individually specifying row IDs, column IDs, you now specify them in bulk, which is a lot more efficient. This NSIndexSet is a new Foundation class.

We also have API for managing sorting UI. By using this other new class called SortDescriptor, I hope you realize this means we don't do sorting for you, just the sort UI for you, but basically we do show, you know, the appropriate, we let the user click on the column headers and you tell us which columns are sortable and how, and we just manage the sorting behavior for you.

And, by the way, we also, yeah, it says they automatically make the state persistent if you've asked your table view to be persistent. The data source, which is what you usually implement, still does the actual sorting, but we tell it what the sort parameters are. And outline view, of course, which is a subclass of table view, has the same behavior.

In table view, we have finer grid drawing control. You can now draw vertical or horizontal grids independently. We have control over background drawing. For instance, if you want alternating background colors, this might have been a way to do it, but turns out we added this other method that says set users alternating background colors, which is the white and blue or white and gray colors you see in a lot of apps these days.

If you want to use those colors in your own lists or tables, we've also added a method to NSColor to return an array of those colors. So white, light blue, white, light blue, it can change depending on the release, whatever. You can also find out the current control tint.

Before, it wasn't easy for you to find out whether the system was set to graphite or Aqua, the blue. You could find out what the current color was, but you couldn't really tell it was graphite or Aqua other than looking at the hue of the color. NSColor also now allows you to set the fill and stroke colors independently. So set fill, set stroke. So these are considered primitives, just like the existing set method.

NSColor to NSImage. We now support PostScript and EPS files. You heard about that, I think, on Monday. We, yeah, I mean, just go ahead and try it and see how it works. I think the first time it's currently a bit slow to set up the VM, but after it's pretty quick and works pretty well. We also support five-channel CMYK images. ImageView now does automatic animation of images.

You can enable or disable this if you want. As you know, we added animated image support in Jaguar, but now ImageView will also do it for you. Automatically. You can now poof it up with this great new function called ShowAnimationEffect. Basically, that's to get the little poof animation.

We have two, actually, animation effects and more to be added maybe in the future. They both do the same thing, disappearing and poof, but if you really want poof and not a disappearing action, you can choose poof as opposed to the other one. It's an asynchronous action and you'll get called back if you want when the poof is done.

And as Cursor now supports images other than 16x16 for applications compiled on Panther, or linked on Panther, the reason for that is we found some incompatibilities by just enabling this. Some applications, it turns out, were already specifying large images, and so we're getting ugly cursor images. So we can't enable this due to compatibility reasons. There's also support for additional standard cursors that you might need in many cases: pointing hand, closed hand, resize, etc. Speech classes.

We have two classes that wrap a bunch of speech APIs. They're quite powerful. You should look at them. I'm not going to talk about them here because, you know, time is short and features are many. Speech recognizer, speech synthesizer, it lets you get back commands for various recognized speech that the user might be saying.

Another thing I'm not going to do just this year is, and so I'm not going to even talk about it other than, well, talk about it a bit, is the controller layer, which is the bindings. You've seen a few demos of this. I think you're all excited to go see the demo this afternoon. It's basically APIs to eliminate the glue code. It comes, it's a bunch of enhancements, you know, in various places. We've enhanced the key value coding, if you're familiar with that. We've also added a new class in this controller and subclasses.

Currently, we have three in the kit, object controller, array controller, user defaults controller. And there's a very tight integration with interface builder, and I will, maybe I will show that, or maybe not if I don't have time. And in fact, that's what makes this feature possible. You know, the feature here is to just raise the bar as far as, you know, avoiding eliminating code you have to write, and the integration with interface builder is a major part of that. There are two talks for this. The one this afternoon, Cocoa UI programming. Friday morning, there was a Cocoa talk, Cocoa performance techniques.

We actually changed that to a second controller layer talk, and it's a continuation of the UI programming talk, where Mark Petrelli will go into more, he will actually cover the APIs in more detail, talk about key value coding, controllers, key value binding, observing. That's Friday morning at 9 a.m., so it's not a performance talk at that slot. It's, the number in the room is the same, the title has changed, so please make a note of it. I think Andreas will probably point it out at today's talk.

So, Interface Builder has support for many of the features and APIs discussed here. Not all, but many. I mean, the Interface Builder team has tracked the changes and we worked with them carefully to make sure everything gets in there. There's support for bindings, there's support for WebKit, as you saw, as a simple palette, and also many of the things we talked about here. There's also some good improved compatibility checking. Let me just give a quick demo of this. I'm going to try not to overlap too much. Ah, too far. Can we switch to the demo machine? - Okay.

Okay, so I'll create a new Cocoa application in Interface Builder. So if you look at some of the palettes here, you'll notice there are some new things. The search field, this is a search field. You can actually drag it out here, and if you bring up the inspector, you'll notice there's even a way to specify the placeholder. You can say Google here, and there you go. It says Google in there.

Let's see. The table view one has some bunch of new stuff. I'll get back to it in a second. Here you see the new box and the new tab view styles. This is the web kit. Currently there is a web view you can drag out, and finally the bindings one down here with three nice colored boxes. Let's drag out a table view here.

Okay. Now, like, just as an example, some of the features we talked about here, you can specify down here, use alternating row background, so you can enable this. You can specify vertical, horizontal grids, as you can see some of the features. Another feature that the IB team added is a way to specify the data cell. For instance, these are now the cells. You notice they're somewhat different than their big counterparts here. And the way you use this is you go here and you drop it. And there you go.

Triangle here lets you set the properties of that data cell object. For instance, I can make them mini controls or I can give them a bunch of tick marks. So there you go. So that's basically how you can customize those cells. If you click on the table column, like I click here, select the table column, the table column info also lets you specify sort key, sort selector, etc. So somewhat more support there. Let's see. Okay, so let me now try to save this document. I will say save.

So note that in the Save panel, it says 10.2 and later format. Can you see this all the way in the back? And that's the new keyed archiving format we added in Jaguar. Now, if I try to specify pre-10.2 format, I will get this warning. And it says, it's 10.2 nib file. It will require data loss. It will result in data loss. And I'll say show incompatibilities.

And this panel here actually-- let me see if I can magnify in on this. Yeah, there we go. So this panel here tells you the critical losses. Basically, this nib won't even open in the old system. And also the losses, like, well, you won't get all the new background colors or whatever.

So at this point, you can choose to delete those incompatibilities or save the file in the new format. OK, so let's see. What time is it? Yeah, I think maybe I'll let Chris come in. So I'm not going to go to the rest of the demo at this point. Can we switch back to the-- slides, please? There's my clicker. There we go.

Okay, the last thing I want to talk about before I invite Chris Parker to stage, oh, there's a demo, is this NSNib class. And it's a new class representing an interface builder nib file. The APIs we had before for nib files was all load the nib from disk and there you go, load it from disk. We've gotten requests to allow loading them from memory for performance reasons especially or for other reasons. You might want to save nibs as flattened data somewhere.

So basically, there's an NSNib class. You can init it with the contents of a URL, so load it from the file system and you can instantiate it over and over while keeping it in memory. Or if you want, you can load it from somewhere else and instantiate it many times.

For instance, if you have a nib that occurs many times in your window, you don't have to load it from the file system over and over again. The other cool thing about NSNib is that these can be archived and unarchived. So the whole NSNib object can be archived and it represents that nib file in its resources. So it's a pretty powerful concept.

You still--I mean, you don't have to use this if you're just loading a nib file from your resources like you normally do, but for more advanced usage, this is the place to look. Okay, so that's it for the AppKit update. I hope I've left you enough time. This is Chris Parker, who is an engineer in the Cocoa Frameworks group. Thank you, sir.

Thank you. My name is Chris Parker. I'm an engineer in the Cocoa frameworks group, and we're going to be talking about the stuff that we've added to Foundation this year. First up, we've added some new language features. There's a new exception mechanism in Foundation, and it's a Java-style exception mechanism that includes a finally clause. So you get @catch, @try, and @finally. It's binary compatible with the old one, and it automatically does a few things for you, like bring variables up to volatile, so that when you throw the exception, things actually work right.

It deals with return statements, and it actually handles continue, break, and go to correctly. So, once upon a time, You would have written something like this using the NSDuring macro and stuff like that. Now we're actually asking you to write things like this using @try. You can return the object directly. There's a catch for exceptions.

You can actually have multiple catch statements here, so as you get more specific ones up front, you can fall through to the more general exception class. There's also a synchronization mechanism now in Foundation. It's a new statement. You can synchronize on any object individually, and it will clear any locks that you've held above the catch point if you throw an exception in there.

So this is the synchronized object. We don't have a synchronized method specifier, so you can only do it on individual objects. And actually, for the exception stuff, we don't have a throws clause that you can put on methods, so you still have to manage that yourself in a way.

We've made some changes now to key value coding, both to improve key value coding and support the new bindings API better. And this is some of the older API that we've had in place has been deprecated and there's a category in the binding header that'll show you which, or the coding header rather, which will tell you which methods those are. We've also got some new more consistently named methods and some new things you can do with it.

So you can actually set values for keys now using this new method and then also you can validate values for keys. And if something does go wrong in validating a particular value for a key, we actually give you a way to report a new NSError back and we'll get to that in a few minutes.

And there's also some methods for dealing with getting whole arrays out for given keys if you send a value for key message to a mutable array. And for all of these methods, there are also key path variants of these, so if you need to go deeper into collections, you can get back more information out from that.

There's also a new API for undefined keys and nil values. This lets you be able to set things up for your own objects where you can specify values for undefined keys. You can set values for undefined keys and you can also set what the nil value is going to be.

New categories on NSArray and NSDictionary for value for key, as well as on NSMutableArray for doing set value and getting values for keys. There are extremely detailed comments, thanks to Mark Picciarelli, in NSKeyValueCoding.h and the companion that we'll talk about in a minute. And it talks about how to modify the behavior for this if you want to change how it works or implement your own methods, and that's definitely good reading.

For key value observing now, this is part of how the bindings mechanism works. You can register objects for notifications about value changes on given key paths. For NSObject and subclasses, you use this AddObserver for key path, specifying some options, and you can specify your own context pointer, which you'll get back later.

For NSArrays, you should use AddObserver to objects and indexes, specifying an index set. This is much more efficient than pinging the AddObserverForKeyPath method over and over and over again. And again, you should use AddObserver for key path, specifying some options, and you can specify your own context pointer, which you'll get back later.

For NSArrays, you should use AddObserver to objects and indexes, specifying an index set. This is much more efficient than pinging the AddObserverForKeyPath method over and over and over again. And again, you specify some options about what kinds of things you want to get notifications for in the context pointer.

What you'll get... There we go. Is this. The observer object will receive an observed value for key path of object with the change and NSDictionary representing the change and your context pointer that you passed in before. So you can attach your own information to these notifications. Observer notifications can be either automatic. You can set it up. You use our methods and we do it for you. Or you can actually drive the machinery by hand. And there are more notes on that in the key value observing dot h header.

In order to make some of this work for large, potentially sparse sets, we've got this new thing called an NSIndexSet. And it's a way to do really efficient, fast storage of large numbers of unsigned integers. And you create one of these basically by specifying either an individual index or an index in a range. You can test to see whether or not indexes exist inside the set.

You can do all kinds of intersection work with it. You can find out whether you intersect indexes in a range. Retrieving indexes, you can pick out the first index and then you can iterate up through them to find out what indexes are actually in the set. And this ties in with a bunch of stuff for table view, for pulling out selected items and stuff like that.

There's a mutable variant so that once you create this, you can actually push indexes in and out of it. You can add indexes or remove indexes by range or by entire index set. So you can specify, "Oh, I've got this index set. I want to take all the indexes in this other one out." Right? So it's fairly powerful.

Sort descriptors. You want to be able to do this for table views. You set up an array of sort descriptors and that describes a sort ordering. And these can also be used for comparing objects. You can specify one object and another object. They'll tell you what the comparison result is based on those sort descriptors.

You can also create sorted arrays from NSArrays and you can pick out--you can take an NS mutable array and basically hand it the sort descriptor and say, "Sort yourself." Here we go. Value transformers, again, another part of the bindings API. This actually allows you to return a new object for some kind of given value and it lets you shift it over into this other object type.

So it will return you the same type or different type with a--you can do it either way. You can transform a value and if it's a reversible transform, you can actually set it up to hand you back the old value. You create these yourselves by subclassing and then you can register that subclass by--you can register it by name so you can get it back easily with the class.

And we've actually provided a bunch of them for you for doing things like negating booleans and nil transforms or not nil and being able to pick things up from archives. So, you know, basically everybody's been asking for that category in NSU user defaults to do colors. You can do it with this too.

There we go. NSError is a new public class for being able to specify errors flexibly. You can attach your own information to these things so that they can bubble up through and you can actually put NSErrors inside of other NSErrors. You create one by specifying a domain using a string. And we've specified a number of different error domains in the headers for things in Foundation and in the kit.

You specify an error code from within that domain and then your dictionary. And there are accessors for all of these things as well as a localized description. And you should use the localized description to be able to provide a meaningful string to your users when it comes up in the UI. NSXML parser after popular demand.

You can set one of these up from a URL. If you need to do it from a file, you can use a file URL or existing data. And you assign a delegate and the delegate basically just implements only the messages that it's actually interested in. You'll get things like starting document or did start element. You'll get some namespace information. You'll get, you know, you can do found comments, stuff like that.

We've also added NSStream to Foundation. This is NSInputStream and NSOutputStreamer for reading and writing. They're toll-free bridged into their CF equivalents. So you can take one of these things and pass it right into the CF APIs that take read streams or write streams. The network streams support basically everything that the CF version does. Secure sockets, proxies, stuff like that. You can also do file and memory streams. And these are subclassable. So if you need to do your own kinds of streams and pass them into the CF flavors, you can subclass NSInputStream and NSOutputStream and they'll just work.

For NS Input Stream, you can set them up with data or with a file at path. And you just read it for a given anticipated length. You'll get back the length you actually read. You can get a buffer in order one, so that it's basically as fast as we can hand it to you. Or you can test to see if there are bytes available on the stream. NS Output Stream, for writing stuff out, you can write out to fixed length buffers.

You can write out to a growing memory buffer or to a file at a path. Same kind of thing, you write a specific length. You get back how much you actually wrote. And you can check to see if it's available. We've also set it up so you can get streams to hosts. Right? So grab a pair of network streams so you can read and write to these things. If you don't want one, you pass them in by reference. If you don't want one, pass nil.

You'll have to schedule these things in order to get events. If you don't want to pull them in, you can do that by sending them to the server. If you don't want to pull the stream constantly for events, you can schedule it to get events off of these things and write in the run loop.

And once you've done that, you assign a delegate and your delegate will get one of these stream handle event messages that will say, "Hey, this stream just had this thing happen to it." So you've got open, whether or not it's got bytes available or you can write to it, whether an error occurred, that kind of thing.

Streams. And, oh, there are properties too for setting things like whether or not you got stuff back out or, you know, out of a memory stream or if you want to set up your SOX proxies, what level of security you want. Basically, all that good stuff. In that line, there have been a number of enhancements to NSURL, as well as the class itself, as well as a number of new classes. This is a short list. You should probably go look at the Foundation headers for this stuff. There will be another session about this later on, probably today and tomorrow. There's one tomorrow.

There's a text URL request to represent what you want to get off the wire, the response for what you actually got back. There's stuff to specify caching policies for downloading URLs once you've got it on disk. Connections and downloads for getting things either right into data or right down to disk. And then also NSURL protocol so you can define your own if you want to support new URL types. There is a modest technology demo on all of your hard drives.

Here's a screenshot. Okay. These are the same APIs that the Safari guys use to get all of their data. They're working off the network. So as they improve it and they get faster, you guys improve and you get faster. So there is another session about this much later in the day. So to wrap up, Jason Guy is going to come up. He's going to sprint up.

Thanks, Chris. So we're going to have a QA shortly, so if you guys want to queue up behind the microphones, that'll be great. In the meantime, let me do a quick roadmap for you all. Go to all of our Cocoa sessions. Lots of really great stuff. The UI programming session 4.12. Late it's day, right here, 3.30. You'll get a lot of really great information on using the new bindings that we've introduced. Later on in the week, Friday morning, session 4.19 at 9 o'clock.

We'll go really in-depth, so you'll see all the APIs. If you're interested in 2D drawing techniques or you want to see some really great tips and tricks for things that we've done in iChat or iTunes and so on, you should really go to that. Take a great look at how we've used the APIs and how you can use the APIs. Lots of code will be in there. The tech session is the last session on Friday, 5 o'clock.

The really hardcore Cocoa folks will be there, so I know you'll all be there. And you missed the first session. Some of you probably did, item 400. But you'll be getting the DVDs, so you can watch it again. And, of course, the feedback forum, very important. We need to hear from you guys. To that note, if you want to send feedback, start with John Galenzi.

He's the manager of software evangelism. He's the one who takes the stuff you guys ask for and makes them do it. If you have API feedback, specific things you want to see in the APIs, send it to coco-feedback at group.apple.com. And if you have technical questions on how to use the API, send it to my team, developer technical support, and we'll help you out.

And as Ali noted, we need a name for that switcher thing. If you have ideas, it's namethatclass at group.apple.com. We've got some great documentation, improving all the time. The API stuff will be documented in the next few days. We won't put documentation forthcoming on there, will we? Okay.