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-412
$eventId
ID of event: wwdc2003
$eventContentId
ID of session without event part: 412
$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 412

Cocoa User Interface Programming

Application Frameworks • 54:08

The Cocoa frameworks continue to evolve, introducing new ways to make your job as a programmer easier and more fun. This in-depth session covers additions to Cocoa that make it possible to develop powerful user interfaces for your applications with even less code than before.

Speakers: Andreas Wendker, James Dempsey

Unlisted on Apple Developer site

Transcript

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

Thank you all for joining us today at the Cocoa User Interface Programming session. 4.12. One quick note, there's another session coming up later on Friday, which is an in-depth version of this 4.19. It's not on your schedule. After seeing this, you will want to go to 4.19. Consider this a requirement. If you don't sit through this, you can't sit through Thank you, I appreciate that. Today we're going to talk about some of the coolest additions to building Cocoa applications out there. And to take us through it, Andreas Wendker.

Good afternoon. So my name is Andreas Wendker and I manage the Web Objects Engineering team. And if you now wonder what exactly I'm doing here and whether you're in the right session, then don't run away, this really is a Cocoa session. Cocoa already is the best and the fastest way to develop desktop applications for Mac OS X. And as you saw in the introductory sessions on Monday, we will make it even better.

To take a look at the existing Cocoa applications out there, you will find that there's actually a lot of code being written simply to keep the user interface in sync with the underlying data objects. What you have to do is you have to pretty much write a lot of repetitive glue code.

You have to add a lot of outlets to your Nib files, you have to set targets and delegates, and you have to implement a lot of methods simply to react to user interface input. That is very straightforward and routine work, but it also takes a lot of time, and frankly, it's really boring.

So we decided to do something about that. And at Panther, we are going to introduce a completely new layer of functionality, a controller layer. This controller layer will automate the handling of your user interface and it will add a lot of features that you've been asking for. And of course, we extended interface builder so that you can make use of these new features without writing code. And the effect will really be that developing Cocoa applications will become a lot faster and a lot easier.

This is a screenshot of FineWord, our code-diffing tool, and I put it here to give you an impression of what impact this technology will have on your own applications. If you imagine your current Cocoa applications on the left side of the picture and the way you would be able to write that same application in Panther on the right side, then as you can see in the bottom there, there will be only one difference. Your code, your glue code will be gone.

So the next hour, I'll give you, first of all, an overview of how the new API works. And I will show you that the concepts of this new technology are based upon the very known model view controller paradigm, which I believe most of you are familiar with. And we'll also show you how you can use Interface Builder to use the new features.

And throughout this session, I will get a lot of help from my colleague, James Dempsey. And he's not only going to drive the demos for you, he also brought his guitar. So if you attended WebObject sessions in the past years, you know this will be good. And if not, stay a few minutes after my summary slide.

And I can say this often enough, session number 419 will be a follow-up session to this one. There's simply so much to talk about in the context of the controller layer that we felt we need a second session. So 419, Friday morning at 9 o'clock. So with that, let me bring up James for a first demo. And he will give you a first demo of how you can use interface better with the new features.

Good afternoon, my name is James Dempsey and I write in-house Cocoa and WebObjects applications for Apple. And what I'm going to show you today is some of the new features in Interface Builder that allow you to access the new controller layer features in Cocoa. So, let's make a new nib file, new Cocoa application. Don't need that menu. And so let's start out by dragging out a good old-fashioned checkbox here.

And we're going to use it to hide or show something, so I'll label it appropriately. The first thing you'll notice in Interface Builder is that we have our familiar attributes and connections, attribute, or excuse me, inspectors, but we also have the addition of this new bindings inspector. And the bindings inspector shows all of the attributes that the selected view item are exposed or have exposed to the controller layer. So they're all things we can configure with this controller layer. You'll notice they're all grouped by category.

So their availability, whether it's enabled or hidden, all different items about the font display, and of course the value. So we've got this little rollover. We click that and we can configure everything about this binding. Now, every application has a shared user defaults controller, and user defaults have values. And within there, we're going to define an arbitrary key. We're going to call it flag, ever popular.

And we have just configured that checkbox to now stuff its value into shared user defaults under the key flag. Now let's have something that actually reacts to that. We'll drag out a text view, which of course is enclosed in an NSScroll view, which has one available binding hidden. We'll hook that up to the same shared user defaults values. And Interface Builder remembers we defined a key, so we can just pick it from the list. And I head into test interface mode, and of course when I click the checkbox, away goes my text view.

And so as opposed to just having attributes that are set-able in Interface Builder, we now have attributes that are dynamic and propagate through the UI on the fly. Now, no IB demo would be complete without a scroll thing in it, of course. So let's hit its value. It's going to go into user defaults of values. And we're going to have it set some font size.

And let's head on over to the Attributes Inspector. The two are not mutually exclusive. You can use both in conjunction with each other. And zero is not a very reasonable font size, so we'll change that. 24 for the... Sure, 25, great font size. All right, let's head on over, type some text into our text view.

2003, yeah, whatever. And multiple fonts allowed, so we have one font. Go to bindings and set the font size up, shared user defaults, going to pull from those values. Again, that font size. Go into test interface mode and voila, I move the slider and something happens in the user interface.

You've seen that before, but in the past you've left test interface mode and everything you did went away. But when you're binding up to a controller object, this one's a shared user defaults controller object, behind the scenes is the actual NS user defaults object that is pushing things into the database. So when I rerun, I persist. So that kind of gives you an idea of how little code your preferences panels might need in the future. Now back to Andreas. Thank you, James. Hi, everyone. I'm Andreas Wendker, and I'm the executive director of Cocoa.

So how did we come up with this technology? Some of you might know that we currently have a technology called EOF, or Enterprise Objects Framework, which is part of the WebObjects product, and it's used for database access. And EOF has a layer that we call the interface layer, and it's used to automatically populate Java swing applications with content from databases. So what we have done is we have taken the ideas and concepts of that layer and all the lessons we learned from it, and we've implemented the next generation of this technology in Objective-C for Cocoa.

So when we set out, when we started, we set the following goals for us. First of all, we wanted to support a large variety of use cases and applications. We certainly didn't want this to be limited to databases. We wanted it to be useful for preferences panels, for applications like Mail, AdWords Book, and all the applications you're familiar with.

We wanted it to integrate easily into existing applications so that you don't have to rewrite your applications completely, just if you want to make use of our features. And we wanted it to be flexible and extensible so that you could get good mileage out of it. We wanted it to be fast, and we wanted it to have great interface integration, and we wanted it to be easy to learn. Or in other words, we wanted it to kick ass.

So I hope that at the end of the session you'll actually agree with me that we achieved what we set out to do. So let me now give you an overview, if I get this right. Let me actually first recap quickly what the Model-View-Controller paradigm is about. With the Model-View-Controller paradigm, you essentially split your application in three parts: The model, which represents your data objects and the underlying logic and rules. And the view, which handles the input and the output of your application, so it consists of all the windows and views you typically assemble in an interface builder. And the controller, which glues these two pieces together. The controller is the glue between the model and the view.

And for the purpose of this session, we'll keep the interaction and the roles and the responsibilities of these three pieces fairly simple. All I want you to keep in mind is that when the user enters a new value in the user interface, The view will notify the controller that a change has happened, and the controller will then apply that change to the appropriate model objects.

But not all the changes in an application happen in the user interface. Sometimes you have the script running in the background, or you might have different views for the same model. So you might have multiple windows open that show the same data. And because of that, controllers also listen for changes from the model objects. They will observe the model objects, and if they are told that the model has changed, they will automatically update the view.

So what are the advantages of the Model-View-Controller paradigm? Essentially, the Model-View-Controller paradigm makes your applications code more reusable and easier to extend. For example, since the model isn't really concerned with the details of the view, it's fairly easy for you to add an additional window of a different type of user interface that shows the same data.

You might even be able to use the same model objects in different applications. And also, since the view isn't really concerned with the details of the model object, you can easily switch the data representation. For example, you can easily change the class that you use to represent your data objects without impacting the code written for the view.

So in the past, you had to write the controller by hand. The glue code that I talked about in the beginning pretty much formed the controller layer of your applications. Going forward in Panther, we will provide you with a reusable component with a reusable controller layer out of the box.

I would like now to give you just an overview of the most important features of our controller layer. Let's start with using any model object. You can apply the new functionality of our controller layer to pretty much any problem domain. Whether you want to display NS documents, whether you want to work on preferences panels and store preference in the user defaults, whether you use NSDictionary's as generic data containers, or whether you use your own custom model objects, you will be able to apply our controller layer to all these models. And we achieved that by using a common data access protocol that we call key value coding.

Key-value coding is actually already part of Mac OS X for quite a while now, but it has only been used in the context of scripting. So unless you have made your application scriptable, you're probably not familiar with it. Key-value coding is a unified way to access properties of model objects by name, or as we refer to it, by key. And we talk a lot more about this in session number 419. It's really essential to understand this protocol.

The second feature, Automatic User Interface Refresh. Our controller layer will make sure, as the Model View Controller paradigm promises, that different parts of the user interface will always stay in sync. So if you have documents with multiple windows for the same document to open, you will not have to write any line of code to keep the content of those windows in sync with the data objects. And we achieved that by using a common observing protocol, which we call Key Value Observing.

So key-value observing allows interested objects, our controllers, to register for change notifications from the model objects. And when they are told that something has changed, they will use that information to propagate the change throughout your complete application. So they will always keep all the views that display the same data in sync.

And that will happen independent of how the change was triggered. So independent of whether the user entered something in the user interface or whether a script was running in the background. And if you don't use multiple windows for the same document, another area where this will be very visible will be in the preferences panels. With our controller layer, changes in the preferences panel will apply immediately to the complete application.

Displaying and editing all standard Cocoa data types. So we really went for the full breadth of functionality in Cocoa, whether you deal with strings, numbers, dates, colors, images, fonts, paths, URLs. Whether you want to display in a text field, in a slide, in an image view, we pretty much have bindings available for all Cocoa widgets.

and we have excellent support for table views to display object arrays. The one thing that we'll probably not get to in the Panther timeframe is support for tree views. So, and its outline views in its browser support for those, we'll probably have to wait for the next release.

Speaking about table views, our controller layer will manage selections for you. It will track which rows the user selected in the table views. And again, it will synchronize the content of other widgets with that selection. So if you have text fields or other widgets that are dependent on the selected row, that show the values of the selected row, you will make sure that those widgets stay in sync with the selection in the table views.

And of course, we will allow or we will handle editing of multiple objects the right way. This is something that actually requires a lot of code to get right, but we felt that it makes applications really more user friendly, so we put it right in the controller layer.

So the features I listed so far are pretty much the essential features you would expect from any controller layer. But we wanted to go further. We wanted to make sure that our features really helped you create polished, great applications. And one area that we found where we could help you greatly is when it comes to handling all these different states you encounter in user interfaces. So the states we will handle for you, first of all, the value state, which pretty much means that a value has not been specified in the model so far.

We also handle multiple selections. We handle the state of no selection. And we even came up with the not applicable state, which is intended to be used if you display different kind of objects in a table view. In those cases, not all table columns might apply to all the objects you display. So you don't want the application to crash in that case. You want it to be handled cleanly. So we will do that for you.

What will happen is that when views query the controller and they ask for the values to be displayed, our controllers will indicate those states through special object values. We call those object values markers. And for all the states that are listed on the slides, we have a marker object. And then the views are informed about the states and can handle it cleanly. And what you as a developer will be able to do, you'll be able to specify placeholder values.

Let me give you an example of that. If you ever used address book or mail to configure new mail accounts, you might have noticed that the forms you have to fill out show some kind of informative text in gray in the text fields until you specify a concrete value. So in our world, that simply is a placeholder for the Nile value state. So placeholders really help you to create informative user interfaces, and I really encourage you to make use of that new feature.

Manipulating object relationships. Most editing in applications is just related to simple values like strings and numbers. If you want to assign a new name to a person object, for example, all you do is you create a new string and you assign it to that person object. But the identity of that string doesn't really have a specific meaning to your application.

Many models are more complicated though, and sometimes you have complete graphs of objects. You might have a graph of person objects and group objects. And if these groups and persons are assigned to each other, you don't want to reference them indirectly through a name or an ID or something like that. You want these objects to have pointers to each other. So we call these pointers that have a real meaning in your model a relationship, and we typically distinguish between two-many relationships, which are just arrays of references, and two-one relationships, which are single object references.

And our controller layer will give you all the mechanisms you need to manipulate these relationships and to traverse them, even if they are multiple levels deep. So one example could be a UI where you have two tables, a table with all the groups and a table with the persons in those groups. So the content of the second table, the person table, depends on the group that is selected, and the content is populated essentially through a relationship from the group object.

Value Transformers. Value Transformers represent an effort on our side to make simplification of our controller layer simple for you. They are very small but powerful objects that you attach to the bindings of the view objects. And Value Transformers are given the opportunity to modify, to convert values before they are displayed and convert them back in a different representation after they've been edited. So essentially you can apply expressions to the values in your model object.

It probably sounds a little bit like a formatter, but it's not limited to strings. It works with arbitrary data types. And also we have a named registry, a global named registry for value transformers, so that you can easily reference them from the Nib files. So you can register your own value transformers in our registry and then just specify them by name in the Nib files, and then this reference will be resolved at runtime. So to give you an idea of what you can do, we are planning to ship a few default placeholders for you in Panther.

One will just negate booleans. That would be very helpful when you give enabled flags and things like that. We'll have transformers that test values for nil or not nil. So what we will do is pretty much we create a boolean depending on whether a value has already been specified or not. And we also have a value transformer to archive values in an NSData. That last one will be very handy when you actually talk to the user defaults database.

Some of you might know that the user defaults can only store plist objects, something like strings, numbers, arrays, dictionaries, and NSData objects. But they can store things like an NS color. So what do you do? In our world, with the value transformers, you can simply use the value transformer to encode or to archive the color object into an NSData and store that in the user defaults. And then when it's read and actually displayed in the UI, it's unarchived again. So these value transformers we expect will probably be the most important way for you to customize our functionality.

The last feature I want to mention is controlling display parameters. We've done a lot in this area, a bunch of different things. And most importantly, probably, we have added automatic sorting and table views for you. This is something that a lot of you have been asking for, and we're finally adding it in Panther.

So what you'll be able to do is you'll be able to click on the table column headers and we automatically sort the content of the table according to that table column. And if you click a second time, you'll reverse the sort order and things like that. We'll show that to you in the next demo.

Beyond that, we simply allow you to manage a large variety of user interface state. For example, what display colors and fonts you want to use, how large windows are, the window positions, the width of table columns, which item in the tab view is selected, what windows are visible, what drawers are visible. And you'll be able to collect all that state and store it either in the user defaults database or within your documents. So when users leave the application or reopen documents they closed before, the application comes up in exactly the same state as they left it.

So now I'd like to ask James again to come up on stage and show you an application that will make use of most of the features that I just listed. All right. I have a little address manager application here. And it basically is using the address book framework to import everything in our address book. And I'm going to show you basically a demo of all the features Andreas just talked about. So first let's take a look at the table view.

You'll notice as I select items in the table view, the current selected item, all of its data gets updated as you would expect. I can sort. Voila, as you might expect. Notice when I do sort and do not have a particular row selected, I get that no selection indicator in the text fields down here. And of course if I have multiple items selected, I get the multiple selection.

Andreas had mentioned, well, let's take a look at groups here. We can add a new group. Call it my Bridge Club. Very exciting life I lead. Make that blue. And let's select four random people. Notice I'm not in my own bridge club. Pick that and obviously that selection gives me all of the selected items take on that value and now the pop-up displays that value. And I've connected those people to a group object, not just a string called Bridge Club. Let's go take a look at the inspector. So I have an inspector that also is changing. Well, everybody works in five infinite loop. That's not very interesting.

There we go. Let me bring up a new document. You'll notice as I switch between documents, the inspector changes on the fly. Let me import from dress book in this one. Voila. We'll go to context. I'll leave it on image. Now. Hit Preferences as well. In Preferences, we can crank up the row height, crank up the font size, and you'll notice that in both table views, it's happening live as we update. Let's save this document.

Save document. And quit the app. When we relaunch and get that document back, you'll notice that we get the state we were in. It remembered that we did indeed have this pulled out, and it's back to the way it was. So that's a sampling of what's in this control layer. Thank you, Andreas.

Do you want to show the project? Which one? The project. Do you want to show the project? Oh, goodness gracious. The kicker. I completely forgot that I had to come here at all since I did so much in Project Builder. Documents. We go to the source code. So let's take a look at the source code for that entire project. It's this much and it mainly deals with grabbing stuff from address book and getting and setting the values into the file system. That's 69 lines of code including the imports and the comments. Now back to you, Andreas. Thank you.

Okay, so the next step, I'd like to give you an overview of the APIs we're introducing in the context of the controller layer. And the APIs can be grouped in three groups. Some utility classes, some controller classes, and a few protocols. The utility classes, the new utility classes, you'll find in the foundation layer. And the first one is NSIndexSet and NSMutableIndexSet.

NSIndexSet is a collection to efficiently manage index information and to store them in a compact form. So that's something that we haven't had, a concept we haven't had before, but it turned out to be really important in the context of the controller layer where we manage a lot of index information, selections and what indexes have changed in the table view, etc. So you will see this class and NSIndexSet in a bunch of our APIs, but it will probably be useful for many other cases outside our controller layer. So I think you'll really like this class.

The second one is an Assort Descriptor. An Assort Descriptor facilitates our automatic sorting in table views. An Assort Descriptor essentially represents sort criteria. So they specify the key that is used for sorting. They specify how the values are compared, whether they are case-sensitive or case-insensitive. And they specify the direction of the sort, ascending versus descending.

And typically, you assemble multiple sort descriptors in an array to specify a sort order down multiple levels. So when you click in the table view, we will pretty much create an array of sort descriptors for you and pass it to the controller layer to actually perform the sort.

Now I already talked about NSValue Transformer. NSValue Transformers are very simple APIs. You typically only implement two or three methods. And it's just a method to convert a value from one direction to the other one and another method to do the opposite. And you can attach them to the bindings to customize or control the layer.

The controller classes in Panther, there will be first of all an NSController class, which is just a super class, an abstract super class of all the controllers we are shipping. And if you want to implement your own controllers, you should subclass that class as well. There's going to be an NSUserDefaultsController. NSUserDefaultsController is specialized in talking to the user defaults database. Typically, you use only one single instance, a shared instance of the UserDefaultsController in your application.

We made sure that the user defaults controller is, to make it really easy for you to access the user defaults, we made sure that the user defaults controller, the shared user defaults controller, is so easily accessible with the Nib files. That's why it was the one controller that showed up in the first demo. So user defaults will be really simple and transparent for you in the future.

In addition to just talk to the user defaults database, you can also use the user defaults controller to specify initial values. So if the user never went to the preferences panel and never specified preferences values, you can transparently specify initial values for those and then they will be just used throughout your application.

and his object controller and then this array controller and his object controller will be used or is used for displaying and editing a single object in your user interface and this array controller is used for displaying and editing an array of objects. And typically you use a combination of those two classes and its object controllers and its array controllers. You typically bind the content of those controllers to each other.

So if you have, you know, a table or let's say a document for a person object, you could create an NS object controller and place the person object within that controller. And if you then want to display the groups that person is in, you create an array controller and bind the content of that array controller to the parent controller, to the object controller which contains the person object and it then traverses the relationship for you.

The protocols that will be important in the context of the control area will be, first of all, NSKValue coding. I also mentioned that in the beginning. It's our data access protocol. And KValue observing is our observing mechanism, so it's the one that we use to receive change notifications from the model objects. And we talk about both these protocols in great detail in session number 419.

Editor tracking is a protocol that I haven't mentioned so far, but it will be also very useful for you. Most Cocoa applications don't immediately submit changes in the user interface to the model objects. Most of the time you wait until the user presses the tab key or the return key and leaves the text field, and only then apply the value. There's nothing wrong with that. You just need to make sure that if you save a document, you capture those last edits.

So with editor tracking, views will be able to tell the controllers that they have uncommitted changes right now, and then with a single method call, you will be able to commit those changes to the model objects. You will be able to force the views to submit their changes to the model objects, or to add editing, for example, before you want to revert.

So bringing up this picture again, key value coding is the protocol used when the view talks to the controller to ask for values and also when the controller talks to the model objects. So the arrows in this diagram don't represent the data flow, it represents who initiates the method calls. And on the way back, we use key value observing to tell the controller and the views that something has changed.

Editor tracking will go back and forth between the controllers and the views. So the views will register with the controllers if they have uncommitted changes, and then the controllers, before a save or a revert, they will commit the changes or they will abort the editing. So those are the protocols.

I'd like to now specify or give you an idea of a few more APIs that you will encounter when you start working with our controller layer. The first one is our key value binding API, which you use to create bindings. There are two methods, and these are methods on the view objects that you want to bind.

So the first method is bind to object with key path options, and there's an unbind method to do the reverse. Let's take a look at the arguments to the methods. The first argument to the bind method is the name of the binding. So it typically represents the property that you want to control. It's something like text color, enabled, or value.

The second argument is the object you observe. It's typically the controller that you bind to. And the key path, the third argument, specifies what value to use when you control the property. And then the fourth argument is simply an end of dictionary of options, simply an end of dictionary with several parameters that you can specify to influence the behavior of the bindings.

What you typically put in this options dictionary is, for example, the value transformer name, and you can also specify the placeholders for the various states I mentioned a few minutes ago. in this options dictionary. You typically don't have to invoke these methods by hand. These are the methods that Interface Builder uses when bindings are established, but you might have to use them by hand if you want to bind objects from different Nib files to each other.

I just talked about specifying the placeholders in the options dictionary. And that is important that you can, for each individual binding, specify placeholders, but we expect that most of the time you will want to use generic terms, something like no selection, multiple selection, et cetera. So to make that easier for you, we defined an API where you can set default placeholder values for your complete application.

And these are class methods, again, methods that you invoke on the view classes, for example, on as text field. And they are called setDefaultPlaceholderForMarkerWithBinding and defaultPlaceholderForMarkerWithBinding. So the arguments here are first of all the placeholder value, then the marker. And for the marker, you will either pass in nil to indicate the null value state, or one of the three object values I listed here.

And it's multiple values marker, and it's no selection marker, and it's not applicable marker. So these are the marker object that we defined to indicate the different states to the view objects. And you simply pass the marker object to the setDefaultPlaceholder method. And then the third argument is the binding name. So per binding, you can define different placeholders.

Another API that will be very useful for you is an API that you can--if you have subclasses of views that have additional parameters that you want to expose to the controller layer, then as long as you have a key value coding compliant--as long as you have key value coding compliant methods for this parameter, pretty much just a simple set and get method. As long as you have that, you can expose the parameters simply by invoking the class method exposed binding.

You typically do that in the initialized method of your class. And once you invoke it to the parameter name, the binding will show up automatically in interface builder and everything else will be taken care of. There's also an instance method, exposed bindings, which returns all the available bindings for an object, including the ones that we provide.

and optionally you can implement the method value class for binding, which is pretty much used in interface builder to match other objects against the bindings. So for example, you can filter out what value transformers do not apply to a given binding. So it's optionally for you, but if you do, it's helpful for interface builder if you implement it.

If you need to go beyond a simple key value coding binding, then you will have to override the bind method at this time. And in the bind method, you have to pretty much register the state that you need for your binding by hand and track that yourself. So simple key value coding bindings are very simple to expose with a single method called. Beyond that, override the bind method and pretty much manage the state yourself.

The last API I want to list here is the API that you use to populate the content of the object and array controllers. The method is simply called setContent. And you can invoke it by hand, manually, or more commonly, you'll probably use bindings to bind the content of the controllers through relationships. The names of the bindings are object relationship and array relationship.

So I'd like to ask James to come up on stage again and give you a third demo of Interface Builder with the more advanced features. Okay, let's make another new nib file. Oops, wrong app. There we go. Another new nib file. This time, let's go a little bit deeper into how I set up and configure these bindings.

So if we take a look, we have a new palette in Interface Builder, the Binder palette. It has the user defaults controller, the object controller, and the array controller that Andreas talked about. And we'll start with an array controller. And if we look at the attributes of an array controller, you'll notice that by default, that array controller is going to be holding onto NSMutable dictionaries, which we can use as a generic container to hold any key value pairs.

However, you can use an NSArray controller to hold an array of any key value coding compliant class in your model. Let's add a few keys. Of course, we can add them on the fly, but it's just a little easier to do it all at once for demo purposes. We're going to put in a flag, a string, and an aptly named number as our items there. And let's hook this array up to a table view. There we go. So we'll add another column, drag that on out.

Get that a little wider. Set for multiple selection. Now, how do we hook this up? Select the table view, let's call this one flag. Go to the bindings and set the value of this. Instead of pulling from shared user defaults, we'll pull from the NSArrayController. The controller key, the array controller has a key that will let us get at all of the arranged objects or just the items that are selected. We want all the objects, so we'll pick that and choose flag for this column. In fact, we're going to make this one of these handy dandy checkbox columns.

You can clap, feel free. For the string, we'll hook that up, shared user, excuse me, that NSArray controller, arranged objects, we'll go for the string. And this time, if somebody hasn't typed in something, we'll put in a null placeholder. So we'll say no value. In the last column, we'll display a number. But this time we'll display it using one of these handy-dandy slider cells.

And we'll set that value up to be NSArrayControllerArrangedObjects. Notice a pattern. Number. And we're also going to just make sure that those cells, click that little widget to get to the cell, has reasonable min and max values. There we go. Great. Now let's add an add and remove button. There we go. Option drag.

We'll line them up all Aqua-y like. Okay. We can use regular old target action. A NSArrayController has an add action that we can hook up to and a remove action that we can hook up to. Let's get a little more room here. and add a text view to show the selected object and a checkbox to show that selected flag.

Again, go to the bindings, hook that value up, shared user, excuse me, that NSArrayController, and this time we want the selection, not all the arranged objects, and we're going to hook that on up to the string. And this time around, if there are multiple items selected, we'll say multiple items selected. That might be clear enough. If there's no selection, we'll say no selection. And if null, we'll say, "Please just type wacky stuff like nothing." And then for the flag, we'll hook that up to the array controller, selection, and flag.

Finally, let's just bring color into this here. And we're going to have this color going to shared user defaults values as a font color. And we'll hook that up to the font color. Where are we? There it is, text color. Shared user defaults, values, font color. Should it work, Andreas? I think so. OK.

Of course, I should say. All righty. So first things first, we hit Test Interface mode, and we can ship. I'm pretty much ready at this point. So we got that no value hanging out there because there is no value. If I select it, obviously, I'll type in there. Bob. Let's add some people. What'd I do? Uh-oh. Oh dear. I broked it.

Alright. For just such an occasion... I did the cooking class thing and worked one out. So let's add a few items here. Honest to God, come see me, it works on my PowerBook. Put in Phil, some Jerry, misspelled Jerry, and Yolanda. Of course, we do all of this fun stuff, give some settings.

We select along and obviously we get what we're selecting. We do a multiple selection. We get the mixed state for the checkbox. We get bobs are both the same value, so it puts the value in there. If we add fill to the mix, it jumps to multiple selected.

Now of course, maybe that's one Bob too many, so we'll get rid of him. We can sort. This is so tough to do. Oh, it's killer. Let's see, is that pretty much the whole pup? I know what I did. Dag Navit, I think I know what I did. And I'm going to show you. I forgot one handy thing that many beginning Cocoa programmers forget, which is that you can't just put an NSColor into the user defaults.

Why? It has to go in as an NSData. So I'm going to use this transformer to do that. And then when it comes back out, I have to turn it from an NSData into a color. Now this was not pre-planned, I just screwed it up, but let's see if that now works. That's fix and continue. I believe that is all that I have, and thank you very much for your kind indulgence.

Thank you, James. So a few more things before I wrap up. I've read about performance. We spent a lot of time on tuning our refresh logic. And if you get detailed enough observer notifications, we actually tuned the refresh down to single cells and table views. So we only redraw the minimum area in the user interface that we have to redraw.

And of course, we added a few caches in the right places to further enhance that. To make you curious of session number 419, through the introduction of key value coding, we introduced a level of indirection. You're not invoking methods directly anymore. You're referring to values by name. So key value coding calls are a tiny little bit slower than direct method invocations, nothing that you have to worry about, really. But if you get into millions of objects on the screen at the same time, you need to know how key value coding works. So you need to use it the way it is intended. And for session 419, we'll talk about all the details.

So if you like this new functionality and you want to start using it, the good news is you don't have to rewrite your application. We have made sure that our controller layer can easily coexist with the traditional glue code that you wrote so far. So we recommend that you start using the functionality soon. You'll probably get a better user experience because of our selection handling, the automatic sorting, the placeholders, the user defaults. You might even see improved performance because of our tuned redraw logic.

And since you'll be able to phase out a lot of your glue code, you will simply reduce your maintenance cost. Less code is always good. And also, if you start using our controller layer, you will be much better prepared for future releases. If we add features in Cocoa in future releases, you'll just be able to get them for free. You just need to start using the controller layer now.

But the seed that you have in your hands is a better version. So there are a few things you need to know if you want to play around with the seed that you have in your hands. First of all, there's unfortunately very little documentation available for the controller layer right now. The documentation is still forthcoming, so at this time we have to point you only to the headers that you find in the foundation of the AppKit framework. And also there are a few pieces missing in the implementation.

Most importantly, the controllers and the seed do not use the key value observing mechanism yet. So when I talked about the automatic propagation of changes to the user interfaces that won't work, what we will refresh automatically for you is all the pieces of the UI that are controlled by the same controller, as you saw on the Nib files here, it all worked. But if you go across multiple controllers for the same model objects, we won't--the automatic propagation of changes won't work.

Also, please treat the available bindings and the names of the bindings as preliminary. You might make a few more changes in there. And another thing that you need to know is that when you start using our value and content bindings for individual widgets-- we are starting to take over the targets and delegates at this time. So if you have a checkbox and you bind the value binding, you will not be able to specify a target action anymore for it.

We will take ownership of that. So we resolved that for the GM. We fixed that, of course, but it might impact how fast you can adopt the new technology. And in general, I'd like to recommend that you use the 10.2 and later Nib file format in interface builder because that greatly enhances compatibility.

So this is all a brand new implementation. It's a brand new feature. And so please submit back reports. It's in your own interest. And also, if you have ideas and thoughts, we'd like to know about them. So please use the Cocoa feedback at group.apple.com mailing list. We won't guarantee your response, but we promise that we will read all your input and take it into concern.

So in summary, in Panther we are adding a great new functionality for you, a controller layer that will automate a lot of your user interface handling. It will get rid of a lot of code that you had to write so far. And we thought a lot about customization with value transformers to make that easy. And as you saw, we extended interface barriers so that you can use the new functionality without writing any single line of code. So with that, it's time for what you've been waiting for.

James! So I guess it was just a little while ago and I had the good fortune to see this technology before it was rolled out here at WWDC. And as sometimes happens with technologies that I get stoked about, the first thing I do is go to the iTunes music store and type in some keywords, see if there are any songs about it. And there weren't any. Not one song about Model View Controller. So then, of course, the next step is I tend to write one. So this year's song is a Model View Controller song.

And once again, I thank you for your kind indulgence. Are we good to go? Am I good to go? We're going to switch over to demo machine, the one Victor's in front of. One or two?

[Transcript missing]

♪ There's a paradigm for factoring your code ♪ ♪ Into functional segments so your brain does not explode ♪ ♪ To achieve reusability you gotta keep those boundaries clean ♪ Model on the one side, view on the other, the controllers in between.

It's got three layers like Oreos do Model view, creamy controller represent your applications rays on detra custom classes that contain data logic and etc you create custom classes in your apps problem domain then you can choose to reuse them with other views but the model objects stay the same you can model a throttle in a manifold model of a two year old model a bottle of fine Chardonnay bottle all the collado stops people say model the coddle in a boil in eggs model the waddle in Hexley's legs one two three four model you you can model all the models opposed for GQ ♪ Cocoa's got a lot of those ♪ ♪ Well written to its credit ♪ ♪ Take an NS TextView, hand it any old unit code ♪

[Transcript missing]

and Probably wondering how data flows between model and view. The controller has to mediate between each layer's changing state to synchronize the data of the two. It pulls and pushes every changed value. Yeah. Model view. Mad props to the small talk crew for model view.

[Transcript missing]

"They model in view very intimately. They often are hard coding which is very foreboding for reusability. any value you select to any view property. And I think you'll stop buying and then you'll be finding less code in your source tree. Yeah, I know I was astounded. That's not even a rhyme. But I think it bears repeating all the codes you won't be needing when you hook it up in IB. Model view, it even handles multiple selections too. Model view controller. Model view. Hope I get my G5 before you.

[Transcript missing]

This is the roadmap for the Cocoa sessions. I make this short, so 419 again. And the Cocoa Feedback Forum is probably the other one that will be important. These are the usual contacts. Again, send feedback to [email protected]. For more information, documentation is forthcoming. Please check the headers at this time.

And we also don't even have demo code available, but we'll try to do that in the next one or two weeks. So please check the ADC member site again, and we'll try to put some demo code there. And with that, I'd like to ask a few colleagues to come up on stage and take some questions.