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

WWDC05 • Session 113

Using Bindings to Help Sync Your Data and UI

Application Technologies • 1:02:00

Cocoa bindings can dramatically simplify your UI code and improve your application's interface and data consistency. Learn how to use bindings as we walk through example code to illustrate how bindings (the "Controller layer") work, how to configure them within Interface Builder, and how to handle common cases in code.

Speaker: Malcolm Crawford

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. Welcome to the weather in England. My name is Malcolm Crawford. I'm a technical writer at Apple. And this morning we're going to talk about bindings. Can I just do a level check quickly? Can everybody hear me in the back? "Can you raise a hand if you can hear me at the back? Good, excellent. Today is not a hands-on session, it's going to be a hands-up session.

I want to check to see how everybody's doing. Can everybody who's got a hand raise a hand?" Excellent. A few missing. Shame. Sorry. So, what are we going to do today? Roughly, we're going to talk about what are Cocoa bindings, what's a problem they solve, and in particular, a slightly different tack on things. We're going to look to see how do bindings actually work underneath. Can we see another hand-raising opportunity here? Who's actually used Cocoa bindings already? and keep your hands raised if you're still mystified by them.

Okay, so what we want to try to do this morning is engage in some sort of a demystification process. So what I'm hoping is that if everybody understands how bindings work, and in particular sees that there's no magic involved in how bindings work, then there'll be somewhat less of a mystery.

So, We'll see how they work and then we'll also take a quick nod at what are controllers and what are value transformers. So, what we'll learn is first of all how to establish bindings, that's a word I'm going to come back to later, establish both in Interface Builder and in code. We'll also look at the underlying technologies. There are three main underlying technologies: key value binding, key value coding, and key value observing. In order to illustrate how bindings actually work, we'll go through the principles of how you would actually go about implementing a bindings-enabled view.

We won't actually look at it in detail. There is some sample code that will be available afterwards for you to have a look at in detail, but we're not going to go through the details. We're just going to look at the principles. We'll have a little look at the role of controllers, and then we'll look at value transformers. To address the first question, though, What are Cocoa Bindings? For those who are still mystified, the simplest way of describing bindings is as a set of technologies that keep models and views synchronized.

Is anybody still mystified by that? I was trying to see if I could find any shorter number of words to describe it, but in principle, all you've got is some sort of view widget, some sort of model or data-bearing object, and values in both of them, and you want to keep them synchronized. That's all bindings is about. So I hope as a concept, that's very straightforward.

Quick tangent on this one while we're here. Notice that I am saying models and views should be kept in sync. There is a temptation, I notice, for some people to try to keep model objects in sync with each other or to bind two view objects together. Please don't do that. That's not the way that it's designed. Things won't work as you expect if you do that. So that may address one particular issue that some people are having. So what problem is it then that bindings serve? solve.

Imagine a very, very simple application. We've got a window on screen that has two UI widgets, a text field and a slider. Somewhere floating around we have a data object that has a single value, a number. We want to keep the value of the data object's number, the value of the slider represents, and the value of the text field in sync.

Typically, that's just--can anybody-- if you're just writing normal Cocoa code, can everybody figure-- who would be absolutely blown away by trying to implement this using normal Cocoa? Has this left anybody behind? Can anybody not figure out how they would do this in normal Cocoa code? I'm going to show it afterwards. Okay. So, trivial, you'd have a whole load of outlets, or a couple of outlets at least, some update code, some glue code. It would be trivial to do, but it's really tedious work.

It's not stuff that you want to have to do every day. And on a simple user interface like this, it's easy enough. But when you have 17 different text fields, when you have three table views, when you have your own custom view, an outline view, and all the rest of it, suddenly it becomes a much bigger exercise and a lot more complicated.

So, we'll illustrate in a moment how to go through that. The other aspect of bind--the other bonus that you get with bindings though is user interface friendliness. One of the other things that you may want to do when putting together a full featured application is ensure that The users presented with a meaningful interface for all values of all of your model data.

It may be helpful if you have a nil value where the user is required to actually enter a value if you place a placeholder into a text field, for example, to tell them that's what's required. If they've selected multiple values that are all supposed to be presented into the same text field, it may be useful to present them with a multiple value marker. All of these things are possible using traditional Cocoa development, but they're fiddly. With bindings, in addition to just keeping everything synchronized, you get this behavior for free.

So, I'll now do a quick demo. So, it's going to be one of the most trivial demos that you'll see ever, I think, at this conference of showing three different approaches to keeping the slider and the text field in sync. For the data object, we're just going to keep things very simple and use a mutable dictionary.

So, To start off with, a very simple Cocoa application. imagine to be named and all I'm going to do is to add

[Transcript missing]

Some of you, who here was ever involved in the Next community? Anybody? Wow. Who here actually saw Mr. Jobs demonstrate this a decade and a bit ago? Okay, so some people, for some people this is going to be familiar. So imagine yourselves in pretty much this exact location displaced by about 300 yards about a dozen years or so ago. This is the demo that Steve Jobs gave back then, and you can connect these two widgets together.

with take value, float value from, connect them together. Ooh. Now, of course, when he did it, he got a huge round of applause, but... That was because that was a big deal back a dozen or so years ago. Nobody else was doing this. I haven't even compiled anything. I haven't got any sleeves to have any code up.

So this was actually quite magical back then. Nowadays, that's of course fatally flawed. The two widgets are kept in sync, but the data object doesn't appear anywhere. If we actually want to record the value that's being set anywhere, we've still got to reach out into the user interface.

So, today, We will draft an application that looks rather more like this, where we have An interface with text field and slider connected up to a controller object, which manages then the underlying data object and action messages. So we've got target action set up for the text field and for the slider, and connections outlets from the controller going out into the user interface. Anybody mystified by that? Straightforward. In the Controller object, we have two outlets, our data object, model object, an action method, and some accessor methods. And the action method, very straightforward. We get the object value from the sender and update everything. And that works. Hooray. Okay.

That's a trivial example, but as I said, think about this then with a number, a large number of different text fields, sliders, what have you. Certainly the number of outlets that you have to deal with, the number of code, the amount of code that you have to write to update everything and so on becomes much more, um, becomes much more of it. With bindings, instead, what we can do is say, let's get rid of the outlets. I'm not bothered about the update method, the action method. So that's code I can delete.

I'm going to go back to

[Transcript missing]

There's no target in action for the user interface widgets. What I want to do -- now, bear with me for this one at the moment. I'm not going to say very much about controllers during this presentation. I'm going to leave that to the next presentation. But a controller here is serving as an abstraction for the underlying data object.

Just trust me on this one. I'm going to add a controller object here and say that the object that it represents, its content object, is bound to the controller's data object. The value of this slider is bound to the number. of the underlying data object, so the underlying mutable dictionary, as is the text field.

If I build and run the application now, first thing to note, if you're watching very carefully, when I ran the first application, the number field was blank, even though There was actually a value for number in the mutable dictionary. It didn't appear. Now, as I've used bindings, that number's appeared automatically. And the two values are still kept in sync appropriately, this time though with no glue code. So that's the simplest example I could come up with for how bindings work. So let's go back and see what we did.

One of the things I found as I was putting this presentation together was there's a lot of talk now about unit tests. We found out we've actually got unit tests for bindings presentations. And it turns out that bindings presentations cannot be given without a Model-View-Controller slide. So this is my Model-View-Controller slide for the bindings demo to get through the test.

Who's not familiar with the Model-View-Controller design pattern? Excellent. I think that--ooh, one person. Okay. Not sure if that was a genuine or somebody just exercising their rights to raise their hand. Okay, excellent. So it's a design pattern--I'll skip through these then. The first example that I showed was basically not an example. No ModelViewController design pattern, simply connecting two UI widgets. This is what happens if you simply bind two View objects together. So this is a reason for those of you who've tried doing this, don't do that.

You're leaving the Model object out of it. Traditional Cocoa binding, we do have a model, we've got a model, we've got a controller class, a whole load of outlets, and in a simple case like the one I just demonstrated, easy enough, more complicated user interfaces gets more difficult.

With Cocoa bindings we use an abstraction in the NSController I'm lying a little bit. No outlets. Often there may be still reasons why you have outlets, but in the example I just showed, there was no need for them. There's no target action, although you can still use target action in your applications. There's no reason to completely dispense with target action where it's appropriate. And there's no glue code.

So, where bindings fits in with ModelViewController, we've already had ModelViewController supported by Cocoa up until now, so models are reusable. The classes that you're given in the foundation framework, views are reusable, app kit classes, and now controls are reusable. Oh, I'm sorry. So the controller that I illustrated was the object controller. The one that you'll typically more often see is the array controller. Again, we're not going to talk any more about these during this presentation. Come to the next one to hear more about these. And then there's a special controller for managing user defaults as well.

So that might beg the question then, well, when do I have to do anything? If it's all this easy. Well, don't worry. There's still plenty of scope for you to add value to your application. Clearly, first thing when you're implementing your own business logic. You can implement your own model classes that are rather more useful than just a mutable dictionary. So plenty of opportunity there for you to add value.

You may want to implement your own custom views. Not every application is made up of sliders and text fields. There may be reasons why you want to subclass Apple's controllers. There may occasionally be reasons why you need to establish bindings programmatically and various other initialization stuff as well. So don't worry. There's still plenty of work that you're able to do to another good living.

So, with that preamble then out of the way, let's turn back to the bindings themselves and look in more detail at, well, first of all, what is a binding? Apologies for -- I'm going to try just reading this definition. So I don't like reading directly from slides, but I will in this case. A binding, I'd like to suggest, is a collection of information that specifies what attribute of one object should be kept synchronized with what property of another with what options.

That's a longish sentence, but conveys the basic idea. It simply says that a binding in the example that we just showed had for a value of a text field can be kept in sync with the number attribute or property of a mutable dictionary. It says keep this in sync with that.

The options bit is tagged on at the end because occasionally there may be transformations that you want to make between the two or you may want to say, well, if that value doesn't exist, show something different up here. But in essence, a binding is simply saying, "I've got a widget over here, a model object over here. Keep these two synchronized." And here, the binding is basically the information that tells you how to keep the two things in sync.

One of the words that I stressed earlier was "Bindings are established rather than created." And I put on there "Think target action." How many people here-- another hand-raising opportunity. How many people here were mystified first time you used-- first time you used target action in Interface Builder? So when you do that "Controll-y Drag-y," I've got a widget-y thing over here, and then I can Control-click in this funny gray line.

So I'm pretty sure that certainly in all the training that I did, most people ended up going, "What? What did I just do?" And then eventually, after you got used to it for a while, you realized, "Oh, well, if I look in the documentation," hint, If I look in the documentation, I find that all these widgety things inherit from NSControl. And NSControl has two instance variables: target and action. All I'm doing when I do that control draggy clicky thing is actually setting those two instance variables. All I'm doing when I do that control draggy clicky thing is actually setting those two instance variables.

Who set up target and action in code? Anybody? So just send a set target or set action message to a widget? Anybody feel that they could not do it if asked? Okay, it's easy. There's no magic there. There's simply instance variables in that control that record the information that you're setting when you do that control draggy thing. That's basically an analogous thing that's happening in bindings. You're specifying a collection of information.

To complicate things a little bit, let's go on a tangent on the different -- there are two broadly speaking two types of binding. Let's also just quickly go on -- mention something about single value bindings and the example that I just gave, I just bound the value of a text field.

You're not constrained just to using a binding for the actual value that's displayed. There may be other attributes for which there are bindings as well. We could have bound the color. We could have bound the font size. We could have bound whether or not the field is enabled. So all of these things are attributes of the text field that could be bound, which is going to concentrate on the most simple and the most obvious one.

That's a single value binding. There may be occasions where you have multiple value bindings. You may have an attribute of a text field or an attribute of some other object whose value depends on the concatenation or combination of other values. So apologies for the denseness of the next slide, but again, it's reasonably simple.

Basically, there are three different types of multivalued bindings: pattern value bindings, value with pattern bindings, multiple Boolean bindings, and multiple value argument bindings. So the first one, value with pattern bindings, the canonical example of that is hash out of hash in a text field where you want to build "Controller" is a text string that tells you how many objects you've selected from a table view.

The actual string value is built from a combination of the number of objects selected and the number of objects in the table view. So a binding that's dependent on multiple values. Multiple Boolean value, we may have "An enabled binding of a button that says, 'This button is only able to be enabled if...' I've got a selection in here, I've got a selection in here, and this value's null.

So all of those things, oh and then sorry, multiple value argument bindings, I'll defer then to Ron's presentation, the next bindings presentation, he'll talk more about those. All of these are things that typically, if you're writing your own code, are difficult to do. Well, actually not that difficult, just tedious again to do. Bindings makes it very straightforward with no code involved.

I mentioned when we were talking about the definition of a binding, keeping this widget value attribute in sync with this particular data property, possibly with some options. There's a number of options that we might set for a binding as well. One of them is value transfer, which we'll talk about later.

Selection markers allow you to do the user interface friendliness to say, okay, well, if I don't have a value for this particular attribute, what do I want to display to the user and so on. And then there may be various other parameters that are available for a particular binding. For those, read the relevant documentation. So there's a huge number of different options that may be set in various different circumstances.

So, now that we know what a binding actually is, how do they work? What I want to do here is go through what I'm -- well, actually, I think I need to give credit to somebody else -- go through a sort of progressive JPEG-style introduction. So what I mean by that is, where I think a number of people have found problems with bindings is it's actually a number of different technologies and aspects of those technologies that you need to understand altogether in order to be able to figure out what's going on. So we've already said there are going to be three different technologies that are required to support bindings.

I could go into detail about one of those technologies, then another, then another, and so on. But as we go through that, all that's going to mean is that, "Okay, well, I understand what this technology means in isolation, but I've got no idea how all of this fits in together." So imagine a sort of progressive JPEG instead where, when you first start downloading a picture, for example, you see this big picture. "There's got some sort of bluish stuff over the top and some greenish, sort of greeny blobby stuff and maybe some browny bits in the middle.

You don't know, well you may guess, but you don't know necessarily that that's actually going to be sky, that's going to be grass, and this is grandma's house in the middle with a sort of smoke coming out of it and what have you. So what I'm going to try to do is say, well okay, let's at least paint this broad brush picture and then go into details and figure out eventually, okay, that's grandma's house in the middle. So we're going to actually see some of the same slides, some of the same concepts revisited on several occasions as we go through this, but in increasing amounts of detail as we go through.

So, first of all then, well actually, well first of all we'll just mention a quick word about design principles, what lies behind this, but then we'll talk about, well how do you actually establish bindings? What are the technologies that underlie bindings? So how does this thing actually work? How are updates propagated through the system? So if you make an edit to something in either the user interface or in a model, to a model value, how does that change propagated? Well then look and see what are the different parts of a binding. So decompose the different aspects of it.

And then finally, we'll just see, well, if you were wanting to write your own bindings-enabled view, what would you have to do? First, design principles. To give a lead into the technologies that are involved, notice the key value parts to those three technologies, key value coding, observing, and binding.

The main requirement for all of these technologies is that they should work with the code that you already have. We don't want to require you to have to write special-- certainly if you're on model classes, for example, we don't want to require you to write particular accessor methods. We don't want our classes to have to know what your custom methods are and so on. We want this to work with any of your classes. So key value coding gives us an abstraction that facilitates this. We'll come back to key value coding in a moment.

Turninging then to how do you actually establish bindings, well, there are two ways. We just saw one way, and that was most of you-- or it looked like most of you already tried this. You can establish bindings in Interface Builder. You can also do it in code. In both cases, it comes down to using the key value binding protocol.

So, quick hint as to where we're going. In both cases, We're using the Key-Value Binding Protocol. So, what is the Key-Value Binding Protocol? It consists of a few methods. The first one, bind to object with key path options, is the one that's actually used to establish a binding.

In some cases, you may actually want to remove a binding, in which case you can use the unbind method. If you're using Interface Builder and you want to create a bindings-enabled view of your own, in order to advertise to Interface Builder what bindings there are available, you can use the "exposeBinding" and "exposeToBindings" method. And in order to make sure that Interface Builder only allows the right sort of thing to be hooked up, you can use value class binding. Most of these, and there aren't very many to begin with, as far as we're concerned as beginners, are pretty much irrelevant.

The only one we're really interested in is this one: establishing a binding. So that's one method, not an awful lot to it. To see how it works, I want to go through a slightly more complicated example. So, this is going to require a little bit of talking through to begin with.

Imagine a scenario where you've written a drawing application. In your application, you have a single graphic object that is able to have a shadow. In the diagram, the graphic object is represented by the blue circle, the shadow by the gray circle that lies behind it. In your code, you may have an underlying graphic object with two instance variables. What you might want to do is to write some sort of an inspector panel.

[Transcript missing]

There are two ways you can do this with straightforward text fields or you may want to create your own custom joystick. class. So the view, the top, in the top part of the shadow inspector, I'm going to call So, in your application, you may have a graphic object that represents The circle with shadow offset and shadow angle instance variables.

Followinging on from or following on from the example that just the demo gave at the outset, we may have a controller object of some description that manages that to which we can make bindings. The bindings that we want to make in this case are going to be four. The first one I'm sorry, there's only five. The first one is actually binding the content of the controller. "We want to bind the value of the offset text field to the shadow offset of the underlying graphic object.

We want to bind the value of the object to the shadow offset of the underlying "The offset of our inspector of the joystick thing to the same value for the angle, we're going to do something a little bit more complicated. We're going to bind the value of the angle text field to the underlying shadow offset of that graphic object, but with a little bit of a difference. This time it's going to go through a value transformer.

If you look carefully, the value in the text field and the value of the shadow angle as represented in the graphic object are different. Let's imagine that, for whatever reason, we're representing the angle in our graphic object in radians. On screen, we want to represent it to the user in degrees. So we'll add a value transformer to this to make it easier.

We can do a similar thing for the angle in the joystick. So we're going to bind the angle attribute of the joystick to the selection's shadow offset. And again, imagine that the joystick is using degrees natively. So it needs to transform the value from the underlying graphic object, which is in radiance, to degrees. So we're going to apply a value transformer to that as well. To begin with, let's forget though about the joystick and concentrate on the more simple.

task of just setting up the bindings for the text field. So, how do we do this? Establishing a binding. We want to bind the value of that angle text field to the shadow angle. of the graphic the way that we saw before was to do that in Interface Builder.

Straightforward enough-ish? Everybody with me on there? So we could simply inspect the binding in Interface Builder, set a number of values in there. To explain what the values are, top left hand corner tells us what the name of the binding is. The slightly confusing thing, and this is analogous then to the control draggy thing that you do in Interface Builder with target action again, is the key path. I'm sorry. Next we need the object that you're binding to.

The slightly confusing thing is the key path. We've actually got two combo boxes which together can specify the key path. So both of these values, if there are indeed two values there, get concatenated. And I think this is one of the things that confuses people. In the big block of widgets underneath, we have a collection of options.

Imagine that we want to do the same thing in code. If we want to do the same thing in code, remember that Underneath, bindings are established using the key-value binding protocol. What did we say there was in that? Just one method. So if you wanted to set up this binding in code, there's just a single method call.

We would have to send a message to the text field to tell it to bind its particular attribute to something. In this particular case, we tell it that it's going to bind its value to a particular object using a particular key path and with a collection of options. So these two ways of establishing a binding are identical. If there's nothing else that you take away from this talk, I'd please like you to try to remember this particular slide.

I hope that more than anything this will help to demystify in particular that inspector in Interface Builder. Is there anybody here who feels they could not write one line of code? Is there anybody here who feels they could not write one line of code? in Interface Builder, think to yourself, underneath is just one line of code. I can write one line of code. That's easy.

It's just a question of figuring out, as ever in Cocoa, well what is that line of code? "So, we now want to see, well, okay, I think you should have got most of the way there already, but let's then drill down into details and see, well, how would you actually figure out what it is that you want to write? I also want to have a look then at, well, what are the other technologies that make all this stuff work? So it's okay saying, okay, we're going to establish this binding.

What do we do after that? Editor value. Consider what happens when the user edits a value in the text field. What happens is key value coding is used to push the new value from a text field down to the controller, applying in this case a value transformer if we specified one.

Key value coding is used to push values from the controller down to the underlying graphic object. Key value observing is used to notify objects, anybody who's interested in changes to values. Key value observing, and in this case, again, using a value transformer if appropriate, is used to notify anybody who's interested in the other value update. So to summarize that, Key-value coding is a technology that's used to push values from the user interface down to the model. Key-value observing is what's used to notify anybody who's interested in changes to underlying model values. And the user interface elements can then update themselves appropriately.

Key Value Coding. And anybody not come across KeyValue Coding before? Okay, one. So KeyValue Coding, very simple API. It gives you a means of accessing an object's properties using a key. So Maybe I'll just click through and encourage you to read the documentation then on this, because it's pretty straightforward then.

The main thing that trips--one of the things that trips people up when using key value coding, particularly for those of you getting on to using core data, is the key value coding for too many relationships. Who's not come across these mutable collection value for keys methods? Okay, so this is new for some people.

So, when you have too many relationships, There are two methods: mutable array value for key, mutable set value for key. These are methods that you can use to manipulate the contents of a collection using key value coding. You can use those methods to retrieve a proxy which you can then send appropriate messages.

So for those of you who've got confused as to why some values aren't updated or found that it's a little bit difficult to manipulate arrays or sets using key value coding, have a look at those methods. Those may be the ones that you want. Keypaths are an extension of key value coding that allow you to follow relationships between objects.

So imagine you've got an employee object that has a manager that's another employee object, and an employee has a first name property. You can ask for an employee's manager's first name by using value for keypath manager.firstname. Important to note here that we're using value for key path rather than value for key. That's another one that trips people up. Similarly, we have set value for keypath to update the value.

Another aspect of key value coding, key value coding validation. So coming back to what can you do to add value to your application, this is going to be again particularly relevant for those of you using core data, but still relevant, but still valuable for people writing your own model classes at the moment.

KVC validation gives you a consistent means of defining validation methods for individual properties. So there's a generic form of the validation method, ValidateValueForKeyError. You can in your own model class implement validate key name error methods. In the body of the method, you can then determine, well, is the value that's being passed in something that I'm happy with? If it is, simply return yes. If no, then first of all create a new NSError object and then return no.

If you look carefully, the input value is typed there as ID*. That's not a typo. You're passed in a pointer to an ID. So within the body of a validation method, you do actually have the opportunity to replace the value that's passed in and massage it into something that you actually want. Generally, we're discouraging people from doing that, though, because of memory management implications. And again, the documentation explains why that is.

So, Looking to see how key value coding works when we send updates. Again, user types a new value into the angle text--into the angle. Text field, type a new value in, key value coding is used to pass that value down to the underlying graphic object. The graphic object, if it implements key value coding validation, does have an opportunity to reject that value if an appropriate flag is set for the binding, otherwise it's updated.

What do you actually have to do in order to support key-value coding? Well, I hope most of you have found actually not very much, for the most part. It's actually really quite difficult not to be key-value coding compliant. "Tipically, all that's expected is that you implement the appropriate accessor methods." Please, that's something you should be doing anyway. Writing and using accessor methods makes memory management a lot easier. So if you implement accessor methods, follow the key--the appropriate naming conventions for accessor methods, life will be an awful lot easier.

It becomes a little bit more complicated for arrays, so the special array access methods you may want to implement. Again, that's covered in documentation. Turn to key value observing the other technology that supports Cocoa bindings in order to actually notify the rest of your application or notify elements of an application of changes to values. There are two parts to KVO.

Think a little bit, think in terms of an analogous thing here, maybe notification centers. If you're using notification centers, there are two parts to using a notification center. First of all, you've got to register to say, "Hey, I'm interested in this particular sort of notification." Secondly, then, you've got to receive messages back from the notification center if the events that you're interested in actually occur. It's a similar thing with KVO. You first have to say, "Hey, I'm interested in this particular property of this particular object." Secondly, you've got to have a means of being told that that value has changed. So registrations go by addObserver for the keypath options context.

The difference between notification centers and KVO is that whereas with notification centers you can specify the message that's going to get sent back to you if the event occurs, with KVO there is a single method that's used as a choke point for all KVO notifications and that's observe value for key path of object change context. So all KVO notifications go back through this one method. So in terms of establishing our binding.

The different user interface elements have to first of all, in order to get KVO to work, say what property it is of what object they're interested in, so they have to register as an observer of the thing that they're bound to. If that value changes, they get a message back. They observe value for key path message.

So to recap, this is how you register. So this is what happens when a binding is set up. This is what happens when a value changes, in this case when a value changes in the model. What do you actually have to do to support KVO? Well, in general, again, not really very much other than simply follow the same "Controller layerissippi" is a key value code that allows you to change key value for key value code.

Support automatically added at runtime. So you don't have to do anything. If you want to, you can disable automatic KVO notifications and switch on manual notifications, in which case you can use "Will change value for key" and "Did change value for key," in which case your accessor methods might start looking like this.

Notice that I've put here the KVO notification methods into an accessor methods. One of the things I've noticed on the list in particular is people seem to want to just sprinkle KVO notifications throughout their code and sort of hope that bindings then start working magically as a result. No, that's not going to work. There's got to be a rational reason for actually posting KVO notifications and typically the place that you would put these methods is in your accessor methods around the place where the value actually changes.

So where have we got to? Three main technologies, key value observing, key value coding, key value binding. You use key value binding to actually establish the binding, key value coding to push values from the user interface down to the model, key value observing to receive notifications of changes of values to the model. You don't have to do very much to actually support KVC and KVO. So now, to look at those in more detail.

Let's have a look and see what you would actually have to do if you wanted to implement your own bindings-enabled view. How would you do the joystick thing? In this, we're going to concentrate still on the angle part of things. So, first of all, establishing a binding. What do we actually have to do? Think back, first of all, to the target action example. With target action, we had a widget that you control dragged, and when you control dragged, you set two instance variables, target and action.

Can I just check, everybody okay with target and action as instance variables of NS control? Anybody still sort of mystified by that? How many people figured out within one day that that's what was going on? How many people did it take one week? How many people did it take a month? How many people forget it out this morning? Okay, it's really like, it's really getting sort of hand fatigue or something.

Okay, so with the control, when we do that control drag thing, we're simply setting those instance variables. So we've got a way of recording the information. What's a good way of recording information in a class then? Well, in instance variables. So if we're setting up the angle binding and other bindings for our joystick, there's a whole lot of information that we need to collect.

Conceptually, at least, one way of doing this is simply to use instance variables. So we can provide our joystick class with a whole set of instance variables in which we can collect all that information. Simple. The one thing that's a little bit complicated at this, lurking down at the bottom, is the angle observation context, which I'm going to add to this. will come back to that later. But at the moment, the main thing to concentrate on is, look, all we've got is a collection of instance variables in which we can store information.

So, What actually happens in our bind method? The bind method is sent when the binding is established, so all we have to do is to collect that information together. So the bind method is a little bit long. Notice the arguments highlighted there in orange. First thing, which binding is it? In this case, we're wanting to set up the angle binding, so is the binding name that's being passed in the one we're interested in? Okay, yes if it is, then.

We must register as an observer of the object whose property This particular attribute is bound to. So if we're saying, okay, joystick's angle's got to be kept in sync with this object's whatever, the joystick has got to observe this thing. That's all that that's doing. So Joystick is saying, "Hey, Model Object, I'm interested in this particular property.

The angle identifier, angle binding identifier is important here because that... particular variable will be sent back to you in the observed message. So what you're saying with by providing that context is, When you tell me that that value has changed, also pass back this context so that I know what it is you're talking about. Remember everything's channeled back through that one single observe message. So you've got to have a means of disambiguating.

Other than that, the next three things are simply recording the other information. So, we need to record, well, what is--what object is it we're actually being bound to, so that if our value is updated, push that through. What's the key path to the property that we're interested in? And then, is there any value transformer? So, in the options, the only thing we're actually interested in, in this particular example, is a value transformer. So, if there's a value transformer, record that as well. And that's it.

[Transcript missing]

for any of the other bindings that we might want to set up, but they all follow pretty much the same pattern. The bind method arguments tell you everything that you're interested in. So you say, "Okay, I need to observe that particular property of that object, and then I need to record that information." And that's it.

What actually happens when there are updates, though? There are two ways in which updates might happen. First of all, view initiated, so if somebody clicks within the joystick to move the shadow angle and offset. Or, say if something's initiated above the model. So maybe if somebody had clicked in the text field and there'd been an update to the model and it had propagated its update.

So, for a view initiated update, imagine that somebody clicks somewhere inside the view, and we channel all of those, so say mouse dragged, mouse down, mouse up, and so on, through an updateForMouseEvent method. So we're going to look at the implementation of our updateForMouseEvent method and see how we would then deal with that using bindings.

What we're going to have to do is update the model, or update the object to which we're bound. Remembering first of all how the binding was established in Interface Builder and what code was associated with that. If we have a look at the code, bind to object with key path options From the perspective of an update that's handled by the view itself, the bind argument tells you "What attribute of your own is it going to be updated?" The "ToObject" argument tells you what remote object you need to update. The "WithKeyPath" argument tells you what property it is of that object and options, whatever other options are specified.

So, in our updateForMouseEvent method, The first thing that we need to do is calculate, okay, what's the new angle for this particular example? Then, first of all, check to see, are we actually observing anything? If we haven't actually been, if bindings haven't been established, then don't bother. So, are we actually observing anything? If so, then, for the options that we're allowed to be set, do we have a value transformer? If there is a value transformer, Apply it.

And then simply update the remote value of the observed object's value using key value coding. And that's it. Really, it just boils down to-- "That penultimate line, not an awful lot to it, and then you can do everything else you want." So pretty simple, I think. Conversely, if the model's updated, remember everything in key-value observing then gets channeled through this one observe method. So from the perspective of the bindings, we can rearrange the order of the bind method a little bit to figure out what's going on.

What the bind method means from the perspective of key-value observing is if the property defined by the argument to the withKeyPath part of the method changes on the object that we're observing, update whatever attribute it is internally that's defined by the binding name and apply any options that were specified.

So in our Observe method, the first thing that we want to do is check to see what the context is that's coming back. What is it that we're interested in? We specify the context when we register. So remember, the context is going to be sent back to us in the Observe method. So this is what we can use to disambiguate different observation notifications.

If it's the one that we're interested in, an apologies then for using short variable names here, but it was the only way everything could fit onto one slide. First of all, find out what the new value is. Secondly, so there's one little bit of a new API here for Tiger. Figure out first of all, is it one of these multiple value marker things? If it's not, then if there's a value transformer, apply it to the new value, and then simply update your own value, update the display, and so on.

Paul's from over there. Again, the long method names and the long, Long variables may make things a little bit more confusing, but really there are only about two lines of important code in there. I don't think that should be beyond anybody in this room if you've paid to come here.

Is that straightforward enough? Does anybody look-- oh, can we just all sort of turn around and just do that? This is my signal that there's five minutes left. Yay, I saw. So, where have we got to? To summarize, we've got three main technologies: key value coding, key value observing, key value binding. Key value binding used to actually establish the bindings.

What I have gone through today thus far is enough in principle for you to understand how bindings, how you can actually create your own bindings-enabled view. I hope that what you have seen from this is there's actually not an awful lot to it. Is anybody still completely mystified by this? That's encouraging.

Is it simpler than some people thought it was going to be? Who still thinks it is horribly complicated? Who still thinks it's a little bit complicated? That's fair. The main thing is it's not horribly complicated, so that's the-- Actually, one of the analogies I didn't make at the outset that some of you probably have heard me make before is that of emergent behavior. So one of the analogies I sometimes like to make is that of an ant hill. I've never actually seen an ant hill, but I would imagine that looking at an ant hill, it's horribly complicated.

You have all this stuff going on, all these ants scurrying around and what have you, and trying to make sense of how they actually built the thing, how all the passages work, how they figure out where to go and food and all the rest of it. It looks horribly, horribly complicated. From the perspective of an individual ant, though, an individual ant is never going to win a Nobel Prize. They're not very complicated animals. They don't do an awful lot individually.

Put a whole load of them together though and you get this emergent behavior. Things look complicated. What I'd like you to try to think of when you look at bindings is, well actually the technologies that I just went through are individually all very simple. It shouldn't have been beyond the wit of anybody in this room certainly to understand any of the technologies individually.

Putting them together makes really interesting things happen though. Sometimes I admit that the way the manifestation of that combination can be confusing. But underneath, just dig through it a little bit, step back and think, well each of those things individually are simple. There's not much to it. Anyway, coming back then to the main thing, because I'm going to overrun now by two minutes again, sorry.

A quick talk about Value Transformers, and then I'll give a quick heads up again about controllers. But both of these are going to be covered in the following talks. So I mentioned value transformers, what are value transformers. You can think of value transformers as being a little bit like formatters but lightweight sort of a formatter.

If you want to use value transformers in instance interface builder you have to register them by name. Foundation gives you a set of three of them. Cocoa gives you a set of three of them by default for testing for nil values and archiving and so on. But you can create and register your own. So there's not an awful lot to the value transformers API.

A method to tell you what class it is that you're dealing with, whether or not it transforms by direct--accepts bidirectional transformation and then methods to actually transform an incoming value. If you want to use an Interface Builder, you have to register a new instance for a particular name, and you typically do this in an initialized method. But other than that, this is the implementation of a Radiance Degrees Value Transformer. Not very much to it.

Again, shouldn't be beyond anybody in this room. "Controllers" mentioned basically I'm just going to say very quickly that there are three different sorts of controller: object controller, array controller, and preferences controller that I mentioned before. Ron's going to talk a bit more about these in his talk. One of the questions that comes up is, though, is why do we actually want controllers? What do they do? Well, one of the most important things is that the controllers give you a degree of abstraction. So rather than binding directly to a model object, the controller gives you a means of changing the model object out from underneath whatever it is that you're bound to.

So you're not hard wiring bindings for a particular text field, for example, to a particular model. More importantly, there are two other protocols that Controls implement-- an Editor and an Editor-editor registration-- which help to ensure that if a user's part way through typing values into a text field when a window's closed, those values are committed down to the model if the window's closed or whatever. And they also provide the selection markers.

So please, please, please do always use controllers. May not seem like you need them, but they're very useful. Selection markers, I just mentioned, are the special

[Transcript missing]

So all of those are going to be things that are covered in the next talk and in the documentation, various other samples, and so on. So I would encourage you to go to the following session.

And if appropriate, Matthew Formica is very happy to personally answer any question that you have on bindings directly, so please email him directly with all of your questions. An alternative, is to use the Cocoa Developeroper list. So a number of you have already taken advantage of that option. But in the interim, the joystick example that I gave is now officially part of the sample code. Read through, have a look at that. Have a look at the documentation and other resources.