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

Cocoa User Interface Programming In-Depth

Application Frameworks • 49:43

Complete with supporting demos and code, this session covers a variety of performance topics and techniques to help you develop fast Cocoa applications. This session's content is aimed at both new and intermediate Cocoa developers.

Speaker: Mark Piccirelli

Unlisted on Apple Developer site

Transcript

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

Good morning everybody. Welcome to session 419, Cocoa User Interface Programming In-Debt. It's the first session of the last day, so hopefully you guys are wide awake. If you're here at 9 o'clock in the morning, either you saw Andreas Wencke's presentation on two days ago, the intro version of this, or you still think this is Cocoa Performance Techniques, it's not. We're going to go in depth on some of the cool new ways of doing your interface, and to talk about it is Mark Piccirelli. Mark Piccirelli Thank you, Jason.

So, good morning. Wednesday we introduced a lot of new technology that makes user interface programming much easier. Now today we're going to talk about the details. In session 412, we let you know about all the new bindings and controllers technology we're introducing. The goal is to automate user interface handling, so you have to write much less code.

It provides some of the features you've been asking for. Of course, we integrated support for it into Interface Builder, and the whole goal, of course, is to make your development faster and easier. and the effect on your application, much less glue coat. So I love this screenshot. A big list of IB outlets just goes completely away.

So what I'm going to talk about today, in general I'm going to talk about what it takes for your model objects to integrate into this system. And the interfaces by which we allow that to happen are key value coding, key value observing, key value binding. We'll talk a little bit about how all the controller classes fit into this, and there'll be some notes about performance at the end. So the architecture that we tried to adhere to while implementing all of this is a classic model view controller.

For Cocoa, Model View Controller means the view classes that we've always had, a full set of user interface controls and everything. Model classes like NS Document and NSDictionary makes a great generic model class. And of course the model classes you provide. Now we're introducing three new controller classes: NSArrayController, NSUserDefaultsController, and NSObjectsController.

We're using the key value coding system that's been in foundation since Mac OS 10.0 and before, actually. We're introducing key value observing in Panther and key value binding, which ties it all together. It's how object relationships are established at nib loading times and things like that. And in the interest of full disclosure, at this point I should admit that on the WWDC seed disk, NSArrayController's there. Key value observing is mostly there, but NSArrayController doesn't use key value observing. So a lot of what I'm going to talk about is a little bit idealized.

But it's definitely all going to be there in Panther, and there's still lots of things on the WWCC worth playing with. And when I give examples today, I'm just going to use the old classic Sketch. I updated Sketch so that the graphics view supports binding and does observing, things like that. And it hooks up to one of the new array controllers. And the draw document got updated a little bit to support key value coding, key value observing, and I'll show you that.

So, terminology. There's some words that I'm going to be using that everybody uses, but not everybody uses the same way. So, today, when I say property, I mean an attribute, a 2-1 relationship, or a too-many relationship. By attribute, I mean something simple, a single immutable value, like the fill color or stroke width of a sketch graphic.

A 2-1 related object is a single object related to another. It's not an attribute, it has properties of its own, so it'll have attributes. An example is the sketch image class, if you've walked through that sample code. The image is 2-1 related to the graphic that holds it. And too-many related objects are, as the name implies, collections of related objects, so the graphics of a sketch document. A sketch document has a collection of graphics. for ethics.

So the first leg of the tripod on which all this is built is key value coding. It's been around for a long, long time. We're making some changes to the implementations of existing API. We're adding new API. And why do you care? Because if you're implementing custom model classes and you want them to work with this binding and work with controllers, they have to be key value coding compliant. And I'll show you what key value coding compliant means.

So key value coding is our system for giving access to object properties using a very generic API that identifies them by key. And by key, we just mean string for the most part. A sketch graphic has -- or I'm sorry, a sketch document has graphics identified by the word graphics, and the individual graphics have properties like fill color.

And you just name the keys, you know, something programmer readable. And these are the same keys that you saw typed into the interface builder bindings inspector in Wednesday's demos. So and in the context of what we're talking about, key value coding lets views get and set values in controllers, and it lets controllers get and set values in model objects.

So the first method of key value coding, there's a bunch, I'm only going to go through like four of them today though. They serve about 90% of the time. Value for key returns the value of the keyed property. What's interesting about what it does is it actually uses the Objective-C runtime to poke around in the class of the model object to which this message is sent. And it invokes an accessor method whose name is typically just the same as the key. So your model classes you get to write in a very natural way, but this API allows clients to access them in a very generic way.

One of the features it does for you, it converts scalar values like booleans and integers and floats to NSNumbers so that they can be passed up through the API and around to different parts easily. So, for example, a sketch graphic has a boolean attribute drawStroke, and the accessor method is implemented in a totally natural way, and it still works. When value for key drawStroke is sent to that object, an NSNumber is returned. An NSNumber is a little bit easier to pass around through this generic stuff than a boolean or an integer or a float would be.

Something new we're adding to Value4Key for Panther is actually inspired by scripting, and we're adding specific support to Value4Key for too many relationships, you know, collections of objects that aren't most easily stored in NSArray. A complicated example of this is in text storage, its scripting support has a too many relationship called words. And to have it pick it all apart and return an array of words every time somebody asks just for one of them isn't really that great of a thing. So we're adding a few more key value coding compliance methods. So you'll have your choice.

You can either implement graphics in the example of this sketch draw document, or you can implement two methods, count of graphics and object and graphics at index to provide access to that relationship. And So, and whatever you choose, the key value coding client, the caller of value for key, can't tell the difference. It gets back an NSArray. Key value coding puts the NSArray together and the client that uses key value coding can send any NSArray method to it, including methods that are implemented in categories on NSArray.

Something new we added just by request was support for key value coding get accessor names that more closely match the conventions that you see in our API. Value for key not only looks for methods of the same name, but it looks for methods that begin with is. So you can write still more natural code.

A brand new method for Panther is setValueForKey, and as its name implies, it sets the value of the keyed property. It's a renaming of a method that's already in there called takeValueForKey, and typically we don't just go rename things in the kit. This is actually in addition to the takeValueForKey method that's already there, but we consider it a renaming. We realized while we were working on this that key value coding was going to get much more popular, more widely used than it has been, so we decided to clean up things like this.

So in the default implementation does the equivalent of what valueForKey would do. It looks for a method whose name fits the pattern and invokes it. So when you send an object setValueForKey fillColor, it will invoke a method named setFillColor. And just like valueForKey does, it does NSNumber to scalar value conversion.

Something that's been missing that we're adding to Panther that's going to be very useful in the context of this UI programming is a new method named ValidateValueForKeyError. And its implementation is supposed to either return a value good enough for passing into setValueForKey or it's supposed to return an error. And the reason this is separate from setValue is because it separates validation roles from decisions about when to validate. How to validate is always a model decision, but when to validate is a UI decision.

So for truly reusable model objects, keeping this separate is a good thing. You might want to defer validation until the user hits the next button on a pane or something like that. And the way you implement this follows a typical KVC pattern. You just have to name the method correctly, and that's it. I couldn't think of an example of this for Sketch, so I picked a zip code, which I think people will probably be typing in a lot. And the method name just follows that pattern.

Something really new for Panther is this method, mutable array value for key. And what it does is it returns an NSMutableArray or something indistinguishable from one that contains too many related objects. And the reason we need this is because you're not supposed to mutate the NSArray that's returned by value for key when the key refers to too many relationships.

So we wanted to support this concept of, you know, a client that's naive of the class to which it's bound being able to mutate sets of objects. So we added this. And the invoker of this method gets to send any NSMutableArray message to the result, again, including things that are implemented on categories. The user of this method really has total flexibility. It's not limited to a specific API when manipulating the data.

But the model class that provides the data doesn't have much responsibility. It just has to implement two methods that correspond to the two most primitive NSMutable array primitives, insertion and removal. So the client of key value coding gets to do all sorts of different things, but the thing that implements key value coding support for that key doesn't have much responsibility.

A concept that will be coming up a lot as I talk and shows up a lot in this UI technology is a concept of key paths. And for each one of the methods I just showed you, there's a variant that takes a key path instead of just a key. And these are actually probably invoked a little more often than the plain key methods. And what's a key path? A key path is just a dot-separated list of keys. And those methods that take key paths pick them apart at the right times and invoke accessor methods.

And those methods correctly. So if you send to some object set value for key path image dot flipped, it'll get the image and it'll effectively send set value for key to that image, which boils down basically to the line you see on the bottom of just getting the image and calling set flipped.

So key value binding is in terms of key paths and key value observing is in terms of key paths. And our controllers use key paths. For example, an NSRA controller republishes the properties of whatever it's bound to. It republishes those properties, you know, of the selected objects and it does it using this key path form. So you have to know about them, but you don't have to do anything to implement them.

So, if you're writing custom model objects, like sketch graphics, for example, here's basically all you have to do to make those classes key value coding compliant. You'd have to implement enough methods for value for key and set value for key and things like that to work. So, for each attribute or 2-1 relationship, you know, single values, you can just implement methods named the same as the key that you've picked to identify that property.

And if it's a mutable property, you have to implement a set method also. If there's validation to be done, you implement the validation method. If there is no validation method, that's fine. Validate value for key error just assumes there's no validation necessary. For each 2-many relationship, like the graphics in a sketch document, you have your choice. You can either implement a simple method with the same name as the relationship, or you can implement a pair of methods, whichever is most convenient in your situation.

And, you know, you can change it after the fact without having to go change other code. For each 2-many relationship that can be mutated, things can be inserted, removed, or replaced in it, you just have to implement this pair of methods: insert object and key at index, or remove object from key at index.

So the demos you saw on Wednesday were great, and they took advantage of the fact that NSDictionary is key value coding compliant. So for simple model objects, don't bother writing the class. Just use NSDictionary. Mark Piccirelli So the demos you saw on Wednesday were great, and they took advantage of the fact that NSDictionary is key value coding compliant. So for simple model objects, don't bother writing the class. Just use NSDictionary.

So the next thing that we're introducing in Panther is key value observing. It's all new API. I'll talk about how to observe. I'll explain why your model objects have to be key value observing compliant so that other objects can bind to them. And I'll explain what you have to do to make your model classes key value observing compliant.

So what does key value observing do? The summary is that it allows objects to be notified of changes to specific properties of other objects. The notifications are very detailed. In the context of this UI programming, it lets views be notified of changes to values and controllers, and it lets controllers be notified of changes to values and model objects.

An observer registers its interest in getting notifications using this method: @ObserverForKeyPathOptionsContext. This isn't part of an informal protocol, and this object really does have an implementation of this that does everything you need. We don't even really expect this to be overridden that often. These messages are actually sent to the individual objects to be observed. There's no observer center that you know about or anything like that. For this to be meaningful, The receiver must be key value observing compliant.

As far as reference counting goes, I think there's probably going to be a bunch of different situations as far as reference counting goes. What's appropriate for the observer to observe the observed object or not. So key value observing just stays out of the discussion. It's API. It doesn't cause any retains or releases. There'll be some standard things that people will do over and over again as far as retaining and releasing, but key value observing leaves everything very flexible. Mark Piccirelli And as you would expect, if there's an addObserver method, there's also a removeObserver method.

So the first parameter is the observer. It's the recipient of notifications about changes to the property identified by the keypath. This observer must implement the NSKeyValueObservingInformer protocol, which is one method, this one, ObserveValueForKeyPathOfObjectChangeCont ext, and I'll talk about it a bit later. Mark Piccirelli And again, as an example of who's observing what, the controls in sketches and specter panel, that I'll show you in a bit, will observe the selection properties of an NSArrayController to which they're bound.

So the key path is just the key path. It identifies the property to be observed. Sticking to that example, selection.fillcolor. And it can identify an attribute to too one relationship or too many relationships. You can not only observe simple values, you can observe collections values and be told when things are inserted or removed or replaced.

Key value observing supports two options right now. We definitely expect this list to grow in the future, but right now there are just two, new and old. And these don't control when observer notifications are sent, just what's in them when they are sent. So new controls whether or not the observer notification has the value after the change, and old controls whether or not the observer notification contains the value from before the change that's causing the observer. So I think in the feedback after the session on Wednesday, somebody asked about automatic undo support, which is something we always think about. And I think this old option will probably be a big piece of that when it comes around.

And there's a context parameter following a pattern that's common in a lot of Cocoa APIs, something that you can pass in that'll just be passed back to you at the right time. And we think people will probably use this for identifying the reason for the observation, when one observer is observing a bunch of different things.

So the notification method, observe value for key path of object change context, is what's sent to the observer for every change to the observed property. And it's very generic. Key value observing doesn't care what you do when you observe. It's meant to be very low level and very generic.

So, and the key path and the object are pretty much just the things bouncing back to you. Same thing with context. Change is an NSDictionary full of the information about what changed. There are four possible entries into it, the kind of change, indexes for the change if there are any, and new values and old values.

There are two basic kinds of observable change notification. The first one is for simple setting. When the key value coding set value for key method is invoked and somebody's observing for that property, this is the kind of change that will be used, setting. If somebody's observing a too many relationship and something gets inserted or removed or replaced, one of these next three observer notifications will be sent.

And for example, when might that happen? When somebody uses that mutable array value for key method and mutates the array that it gets back, something like this will be sent to any observers. and in the case of insertion, removal, or replacement, it provides the indexes of the objects that are inserted or removed or replaced using the new NSIndexSet class we're introducing in Panther. It doesn't make sense for simple setting changes, so it's not there then.

In the last two entries of the Key Value Observing Change notification are old values and new values. And, you know, these aren't there if the observer didn't specify it wanted them when it registered as an observer. So for simple changes, settings, these are just the old and new values of the property. For insertions, removals, and replacements, these are actually arrays of the objects that are inserted, removed, or replaced.

So how do you, what does your model class have to do for these key value observer notifications to be sent out when properties in your model class are changed? Well, there's the pretty easy way and the really easy way. This is the pretty easy way. You just have to surround the change with indications of will change value for key and did change value for key.

and in the case of too many, that was for attributes and too many relationships. For too many relationships, when collections of objects are being changed, the methods you have to invoke are a little more detailed. Will change and you have to specify removal replacement or insertion. The relevant indexes and then again the key that identifies the too many relationship.

So that's not so bad, but we don't even want to force you to have to write that much stuff into your model classes. So we're introducing a feature called Automatic Key Value Observer Notification, and it's actually on by default, so you don't even have to do anything to turn it on.

And what Automatic Key Value Observer Notification means is whenever any of those key value coding methods, like set value for key, is invoked, that will cause an Automatic Key Value Observer Notification to be sent out. And not only that, but indications of key value coding compliant methods result in observer notifications.

So not only does setValueForKey messages cause observer notifications for that key, but so do implementations of the accessor methods for that property. And not only do mutations of the result of mutable array value for key cause notifications, but when anybody sends an insert object in key at index or a move object from key at index message to an observed container, that will cause key value observer notifications.

So you don't have to sprinkle "will change value for key" and "did change value for key" all over your code. If your model objects access their own values and each other's values consistently through key value coding compliant methods, we'll do the rest. You know, simple set methods, just keep using those. You know, you might already be using those and it'll just automatically work. So and of course, there are a couple of situations where you can't go through those key value coding compliant methods. And even when you're using automatic key value observer notification, the manual mode keeps working.

So, key value binding is the third leg of the tripod that all this sits on. It's a brand new API and it's what ties it all together. It's what allows the value of an object's property to be tied to the value of another object's property. And this API we're introducing provides plenty of flexibility so that objects can support binding options that we can't even anticipate. And key value binding, when it's being used, that implies that typically key value coding and key value observing are being used too.

So this API, this key value binding API is used at nib loading time typically. It can be used at other times of course. And views and controllers get hooked up to controllers and model objects. Key value observer or key value observers are registered with the things that they're observing. UI controls at that point take responsibility for updating whatever they're bound to whenever the user manipulates the value that they're presenting. And of course all the app kit classes to which we're adding binding support do this.

So this is what the method looks like. It's just bind to object with key path options. And this is, again, it's sent at nib loading time. You can use it at other times, too, for more complicated situations. But for a while, this will probably -- we don't expect too many uses of it, you know, other than nib loading time, but it's there for you. So and, of course, there's an unbind method, too.

So the parameters are the name of the binding and a lot of these look like key value coding keys, but they don't necessarily have to be. And for example, NSControl exposes a value binding and NSTextField exposes an editable binding, things like text color too. The other parameters are what is being bound to, the object that contains the property to be bound to, and the key path of the property. And there's a dictionary that takes options.

So I think Andrea's covered most of these options pretty well on Wednesday, but just to refresh your memory, things like value transformer, something that can manipulate the value for, you know, as part of more glue while things are moving around. Placeholders, the marker values that come out of controllers for complicated selection situations become placeholders that are presented in the UI. And any options that are specific to the binding. So, controller classes, they're the first big clients of key value coding, key value observing, and key value binding. There is an abstract superclass, NSController, and three subclasses, NSArrayController, object controller, and user defaults controller.

So, NSArrayController is what you would typically bind a table view to now. And NSArrayControllers have a too many relationship named arranged objects. They're the set of objects to be presented to the user after any sorting or filtering or whatever is done. On the other side of the Arrange Controller, you can bind it, its array relationship, to the too-many relationship of a model object. In our example, for example, the graphics of a sketch document are what the Array Controller we're using binds to.

So key-value observer notifications from the model object cause key-value observer notifications to be sent to the table view, first to the Array Controller, then to the table view. And the Array Controller just doesn't pass them straight through. It updates them to take things like sorting into account, because that's what the table view is thinking about as arranged objects. And it also keeps the selection up to date. When objects are removed or inserted, it makes sure that the selection that's showing in the table view still makes sense.

And in addition to binding an NSArray controller to a relationship of a model object, you can just use the set content method that it publishes and let it manage the life cycle of an array of objects. You don't have to bind it to anything. You can just let it do all the work for simple situations.

So the first big feature that an NSArrayController has is selection management. You combine the selection indexes of a table view to an array controller's selection indexes. And when you do that, and you've also bound the selection properties of an array controller to UI elements, whenever the selection changes, key value observer notifications are sent to the UI elements.

So, for example, a color well that's bound to an array controller's selection is notified whenever, in this example, whenever the fill color of the selected graphics changes. And that might happen either because the fill color of an individual graphic changed or the set of selected graphics changed and all the different situations that would cause that to be updated in the UI.

NSRA Controller isn't just for binding, it provides a real API of its own, you know, big set of methods you get to call, and just a selection of them. NSRA Controller has built-in support for user-friendly selection behavior. A few flags like avoids empty selection, for when that's appropriate in a table view, preserves selection so that things are being inserted and removed around the selection, the selection stays still, and selects inserted objects for when that's the right UI behavior. and for situations where the array controller is being manipulated by some other code of your own, you can get it all the things like the selection indexes using methods like set selection indexes and add and remove.

The other big feature that NSArrayController supports right now is sorting. So you can bind the sort descriptors of a table view to the sort descriptors of an array controller. So as the user is clicking in the table column headers to change the sort order, the table view tells the controller that the list of sort descriptors has changed. And when it does that, NSArrayController, you know, actually does the sorting and sends out key value observer notifications for the arranged objects relationship.

So that was an NSArray controller. NSObject controller is also there, and as its name implies, it controls a single object instead of an array. So why is it useful to bind a UI control to an object controller? It's because you can bind an object controller to something that might be coming and going. It will observe a 2-1 relationship in another object.

And it does clever things like handling the situations where that 2-1 related object disappears or the type of it means that the bound to property is no longer applicable. So in general, NSObjectController serves the purpose of generating these marker objects that you heard about on Wednesday that get converted to placeholder objects that show up in the UI, even in simple situations. So just as with NSArrayController, for NSObjectController, it has a set content method, so you can just let it own what's being presented.

and the third new controller is NSUserDefaultsController. We saw demonstrations of that on Wednesday. And what you do is you bind the values of UI controllers to the value of a UserDefaultsController, you know, some subproperty of it, the key for which, you know, you get to pick the name. So not only can you do that, but you can observe NSUserDefaultsController.

So other parts of your program that want to know immediately when the preference has changed can just register themselves as key value observers of those properties in NSUserDefaultsController. It also supports handy support for setting the initial values of preferences, you know, the factory defaults. And shared UserDefaultsController is easy to get to in IB. You saw it being picked from the pull-down menu in the Bindings Inspector on Wednesday. So let me show you some of this code I'm talking about.

So let's say that Sketch was so useful that it was worth packaging up and making sure that it was properly reusable. The first thing we would do in doing that is adding binding support to its graphic view. And here's a simple implementation of the key value binding method that I told you about.

This Sketch graphic view supports two binding names. One is graphics, the list of graphics to be presented in the view, and selection indexes, just the, you know, which graphics are selected. So the implementation is pretty simple. All it does is it just stores a pointer to the container of the graphics that's being passed in, the key path that was specified.

And then it starts observing that container of graphics. Both graphics that are being inserted and graphics that are being removed so it can update the display. I'm sorry, removed while that's happening. And the context it specifies, just so it can identify why it's getting these observer notifications, is just One of a handful, you know, simple ints. It really just needs them for identification purposes. And for selection indexes, it does a similar thing. It records the information about what the graphic view is bound to and then adds itself as an observer. And then it updates the display.

So Sketch's draw document, for it to allow things to bind to it, it has to be key value coding and key value observing compliant for this graphics relationship that it publishes. This is all it takes to do to be both key value coding and key value observing compliant for that relationship. Just something that returns an array of the graphics and a method that handles insertion. And in this case, it still has to do its own undo support. And In addition to doing the actual insertion, it also tells the graphic. will be joined by the panel of speakers.

For individual graphics, individual graphics also have to be key value observing compliant so that the Sketch graphic view can observe them, can be told when they're changed so it knows to update the screen. The first one I'll show you here is set fill color. And I didn't have to change this at all. This is already key value coding compliant. And because we're using automatic key value observer notification, it's already KVO compliant. So no changes necessary for this one.

Mark Piccirelli For set stroke line width, it does a little more. The line width of the sketch graphic affects how large the graphic is on the screen. So it just manually says when the line width changes, the drawing bounds change. Mark Piccirelli And actually, there's another feature that's going to be in Panther called set keys trigger change notifications for dependent key. Mark Piccirelli A mouthful.

But this is what you can use to indicate things like the drawing bounds. Mark Piccirelli Of the sketch graphic depends on the line width. So this will change value for key and did change value for key. Mark Piccirelli It won't even be necessary in this situation, though. I should leave it in just so you can see what it looks like. Mark Piccirelli So.

So we just run this and it's Sketch, you know, Sketch, that's all. So it has an inspector panel. And here I'll select them all. So as you change things, that just works. So, and I'll show you the code for the inspector panel in a second. is the owner of the software. The code for the Inspector Panel, I think you can see this coming, is automatically updated on the screen.

I'll show you some of the bindings in the nib. This is pretty neat. IB gives you a nice summary of what's going on with the bindings. So the checkbox here for controlling whether or not the graphic is filled is just bound to the selection.drawAsFill of an array controller. The fill color is bound to selection.fillColor of an array controller.

And actually, it's really not appropriate to leave that enabled when that checkbox is not checked. So you can bind the enabled binding of the color well to selection.drawsFill. So, and so on. So because of all the binding support in the Inspector Panel and because, you know, NSRA controller is taking care of everything for you, here is the source code for Inspector Controller, which is no longer part of the project.

I got to take all of it out. So this is not actually built into the project anymore. So how many lines of code got to go away because of that binding support in Inspector Panel? We won't count a copyright notice. Mark Piccirelli So about 250 lines. So it has to go completely away.

So the last thing I'll talk about today is performance. Some of what we're doing to make sure that the new technology is fast enough to use and some performance notes about being key value coding compliant and key value observing compliant. So as I mentioned, observation info is actually associated with each individual observed object. And that might sound expensive to you.

You might imagine, oh, no, that means that there's going to be twice as many objects in my system, each object and then the observation info for each object. And no, that won't be the case. We're actually taking great care to make sure that when multiple model objects are being observed in the same way, same set of observers, same keys, same things like that, the memory that's allocated to record that observation is shared between the individual observed objects.

Key value coding's performance has always been very important and we're making sure we don't ruin it with key value observing. So set value for key has a certain cost to it and we're making sure that cost isn't going to go up inappropriately when somebody is observing that key for that model object. So in the general rule we're following is that we're providing good default implementations for everything, but we're open to optimization, but we're leaving things open to optimization for specific cases, which I'll show you.

One piece of advice for you, value for key, don't override it. There's a bunch of performance tricks we can play as far as caching Objective-C runtime info goes, but all those tricks are effectively defeated if value for key is overridden. So in general, just stick to the pattern of implementing key value coding compliant accessor methods.

So I mentioned that we added the support for implementing key value coding compliant methods of the form count of key and object and key at index. Those are required if you're using that pattern of giving access to relationship. If measurement says it's worth it, you can also implement a method whose name follows this pattern, get key range. So those first two methods correspond roughly to the primitives of NSRA. And this next method corresponds pretty much to another NSRA method that you can override.

For mutable too-many relationships, you have to implement these insert object and remove object methods. You can also implement a replace method if it makes a difference in your too-many relationships case. So that's just two optional key value coding compliant methods. We plan on adding a bunch more in the future as we get more experience with this, see how people are using it, and see the performance issues that need to be dealt with.

And for example, we might add more optional key value coding compliant methods that let you insert and remove ranges or work with the new NS index set class that's being introduced in Panther. So and whatever we do though, we don't intend to change the list of methods that's required to be key value coding compliant.

As far as using key value coding goes, the advice is don't overuse it. So if you're converting code, making it more generic, letting it support bindings, and you're converting implementations of simple methods to use as a value for key and mutable array value for key, that might be worth measuring when you're all done with that. These methods are pretty fast considering what they do, but they will always be more expensive than a simple Objective-C message dispatch, so you should check that.

When you're using value for key and getting an array back, or using mutable array value for key and getting a mutable array back, what we're suggesting for now is try to use it just like you would a normal NSArray or NS mutable array. Our intent is that the performance characteristics will be pretty much the same as a real NSArray or NS mutable array. So when that's not the case, we want to hear about it. And if you see optimization needs to be done, try and keep that in the model code and, you know, where it will be more reusable.

As far as efficient key value observing compliance goes, there's a pair of methods that you get to override if you need to, and I think typically you won't, but they're called set observation info and observation info. So when large numbers of objects are being observed, the observation info is actually stored separately from the object and associated with a hash table. And that should be good for most of the time, but there may be situations where it's not. And when it's not, we just want you to give us four bytes of instance variable space and let us put the observation info there.

and in general with key value observing, take advantage of the fact that these observation notifications are super fine granularity. It just doesn't say that the object changed, it says that this property of the object changed. So, you know, don't cause key value observer notifications to be sent out when nothing's actually changing.

And on the other side of it, don't observe unnecessarily. So the app kit views to which binding support are being added take care not to observe gratuitously. The best example of this is table view. When a table view's row objects are bound to too many relationships in a container, for example in an NSArray controller's arranged objects, which will be typical, if the table view, if there's like 100,000 rows in the table, it doesn't observe 100,000 objects, it just observes the 50 that are visible at any one time.

And we're taking care to make sure that adding and removing one object as an observer of another is fast enough to make that feasible. So there isn't any noticeable overhead while you're scrolling a table view caused by the fact that the table view is deregistering itself as an observer of objects. So the table view is just a scroll of objects as they scroll off and registering itself as an observer as they scroll on.

So one more pair of methods I haven't told you about yet. It's the bulk variant of AddObserver and RemoveObserver. So the same set of parameters as the AddObserver and the RemoveObserver I've already shown you, but it's sent to an NSArray and it takes an index set, identifying the objects to which KeyValueObserver should be added or removed.

So, and in general, you know, there's a little bit of work that has to be done when one object adds itself as an observer of another. With these methods, that little bit of work is only done once. Basically, the observed objects are just told, you know, here's your observation info, hold on to it for me.

So that's pretty much it. On Wednesday we introduced great new technology to make User Interface Programming much easier. And today we talked about what it takes for your custom model objects to hook into that. So it basically boils down to being key value coding compliant and key value observing compliant.

And we've worked pretty hard to make sure that that's going to be fast and easy for you. So I hope you all give what is on the WWC seat a try. It should work pretty well for you. And we hope you write great custom maps with this. Thank you.

[Transcript missing]

Okie dokie. There we go. So, John Galenzi is the person you want to talk to if you've got some information, feedback, what have you, on all the Cocoa stuff that you've seen at the show. If you have general API suggestions, they should go to coco-feedback at group.apple.com.

Those go directly to the Cocoa engineering team. And if you have code level questions, they should come to my team, developer technical support, and we're happy to help you. If you need more information, we've got no documentation. But feel free to check the headers. We will have documentation for Panther.