---
title: WWDC2004 Session 416
framework: wwdc
role: article
path: wwdc/wwdc2004-416
---

# WWDC2004 Session 416

## Transcript

Kind: captions Language: en cool good afternoon everyone welcome to session for 16 this session will be all about using and customizing cocoa bindings my name is ron lee sang i'm a glue code architected Apple I work on the cocoa bindings technology which we introduced last year at WWDC and then shipped in Panther as the controller layer for Coco this year I'd like to take the next hour so and talk about for high-level topics starting off with a general overview of cocoa bindings as a technology and how it can speed up your application development and raise the quality of your applications and then I'll talk about some of the new features that we've added to cocoa bindings since the last release and then I'll finish off with some tips and tricks for using cocoa bindings in your everyday development including a section I call roll your own bindings where we'll talk about making your view and model subclasses more bindings friendly so let's see so let's start off with the overview of cocoa bindings if I've told you once I've told you a thousand times model-view-controller so to understand cocoa bindings you have to be familiar with model-view-controller I'll say it again you separate your application into three distinct layers the Model View and controller layer and the controller layers the part that keeps the whole application together synchronizing the data from your model layer with the display logic in your view layer and that's why it's called glue code any cocoa developer will look at this diagram and see Oh view layer logic app kit helps me with that and then you can see that the model layer logic is is built with foundation code as well as now core data then the glue code is left up to you you do that part well you did until cocoa bindings so now we have a reusable controller layer so that you can toss out all that glue code writing much much less code to get the same functionality yeah that's right so to give you an idea of exactly what the clicker does there we go so now Coco bindings can complete the picture of MDC the Coco way it provides a reasonable set of controller classes that abstract the interaction with model layer objects and also Coco binding Springs with it the notion of a binding which simply says what attribute of one object should be kept in sync with what property of another object simply description of how to bind the values between the two objects so let me just go through the technology base on which Coco bindings is built there are three distinct protocols that are in Coco that are required for the coco bindings technology to work the first most of you are probably familiar with key value coding then there's key value observing which we introduced last year and key value binding key value coding is an informal protocol that lets you access members of an object by name indirectly that we don't directly access it by instance variable or sending methods method messages directly p value observing lets you describe what object how an object should be notified of changes from another object so that an interested party can be notified when something changes in an observed object key value binding is provides a mechanism for establishing a binding for creating that finding that that definition of what should be kept in sync with what other object the way this works in actual mbc objects is all of the values that are transferred between the layers are sent via KABC so key value coding messages are sent all the time to notify to send values between the model and the controller the controller and the view then key value observing is used for the view for example to register itself as an observer for the controller that way any changes to controller like for its selection the name of its selection can be sent a notification for that change can be sent to the view this is how it knows that something's changed well specifically this is how it knows that something's changed the view implements a method also defined by a key-value observing the observed value for key fast method this method is invoked on the view object on the observer whenever something in the controller the observed object changes key value binding lets you bind a view or multiple views to the same controller object this is how the view knows that it should add itself as an observer of the controller so during a typical edit cycle when the when the user is actually interacting with the view something changes in the view and it will propagate the new value to the controller the controller can then on behalf of the view send that new value onto the model object thus keeping the view and the model in sync furthermore when something does change in the model the model can tell the controller by a key value observing but something has changed and again 124 and again the controller can notify any other views that are that are registered with the controller this way not only do the view stay in sync with the model objects but views in the same view hierarchy can stay in sync with each other and all of this is done with the magic of interface builder so you can actually configure these bindings in ib it's not a code you can still configure bindings I code but you've got I beak so think next is a short demo of how exactly this looks an IB will go to demo to I believe so we have a simple mid-season called simple interface builder Oh could I get the other other scan please yeah one more there yeah all right thank you so uncluttered it here I have a simple window and another simple panel hooked up to a simple array controller here you can see I've defined that the NS array controller uses immutable dictionary for its model objects and that my table is bound to my array controller and it's displaying the name of all the objects in the array controller and also the preferred food of all the people displayed in the array controller I'll just show you how this all run a few tests interface alright you can add a couple of items here let's go I like pizza and say andreas who likes chocolate egg now all I think is a sushi guy so we can edit all these values and you'll see here that these text fields up at the top are kept in sync with the number of objects that are in the table there in the array can remove and add and remove and add and we've also we also have multiple selection so we can count how many things are selected you can even edit other values like the favorite language of each of these people pretty sure Angelica German I think bill like foul language can remember so and you know I can change the attributes of the text field here the display attributes so the text font size on a little isn't supposed to be a preferences panel that yeah well and even the text color oops oh there seems to be a break in the binding here let's go let's go update that so here you can see I have my text color binding down to the shared user default and here in the color well oh it wasn't highlighted well you get the idea the text color really does normally change so we can do all this stuff without writing any code all ni b we get a lot further developing our application just finishing the interface in interface builder so this is what Koko bindings will give you if we can go back to the slides crouching tiger hmm okay so that ends the demo that's also the end of the overview section how many of you guys have actually played with bindings already by the way oh yeah maybe you have like like never heard of cocoa bindings before raise your hands it's okay are you okay so then the overview isn't completely without merit so that's the end of the overview now we go into new features things that we've added for Tiger added to cocoa bindings for tiger the first few features that I'll go over are the result of a lot of feature requests the first will be a tree controller so that now you have something to bind to from the outline view in the browser and we also have filtering built into the NS array controller so you don't have to subclass anymore glad you like it let's I'll show you a little bit more about each of these first with the tree controller with the tree controller we wanted to make it as easy as possible to get used to using it so it kind of feels a little bit like using the array controller except of course the array controllers manager raised but the tree controller manages a tree of objects but that tree isn't specifically nens tree class or you don't have to import your data into any specific class or re-architect all of your objects we just expect that you have what is probably natural for all of your data as far as tree goes that you have a raise of objects that have arrays as children objects of a raise of the raise so this graph up here pretty much sums up what what the tree controller expects with your data if you can describe your data this way then you can use your tree with the tree controller all you have to do is describe to just just describe your tree and the main thing for that description is the children key they'll feel if you set the children key of the tree controller that's what the key that's the key the tree controller will use to traverse all of the nodes of your tree so this has the caveat that all of the objects in your tree have to respond to this children key key this can usually be done by subclassing or by having a category or changing the source there are also some optional keys that you can set the leaf key and the account key which offer some optimizations for whether or not the tree controller should reverse children there then of course there are some actions that we expose for the tree controller so you can bind buttons to it for adding siblings to the selection as well as adding child objects to the selection and removing any of the selected objects from the tree controller and then after you've set all the keys and set up your tree controller you need to tell it where the root of the tree is you do this with either a content object binding or by explicitly setting the content object the same way as an outlet just using an outlet from there the tree controller will start managing the tree of objects there also some extra key that we've added they look a lot like the array controller controller keys starting off with the arranged objects which returns the root of the tree after any sorting has happened to the to the child object then there's also the selection that knows how to manage intelligently multiple selection no selection not applicable the turning the appropriate key value binding markers and we've added a couple of keys just for convenience in interface builder can insert child and can add child we also have cannon certain can add in just plain form so that now you can find the enabled value of one of your buttons so that if the tree controller doesn't support adding a child then the button consid disabled we've also added selection index paths of the controller key which is the same as selection in dec is that's because we needed something different to identify nodes in the tree you can think of the NS index path which we've added the foundation as the identifier for nodes in the tree it's similar to thinking about how you you access elements of an array by index except now we have a path of indexes that represents all the children of each node that you traverse through the tree so here for nine would indicate the child at index nine of the childhood index floor of the childhood is index two of the root of your tree it's a condensed way of representing each node in your tree so now that you have the tree controller you can bind dns outline view to the tree controller and the NFL lines use table columns that looks again exactly like binding a regular table view table column to the array controller you just find the values or text or font size or anything and then you bind the content and selection index path of the outline view to the tree controller the content binding gives the outline view all of the objects basically the root object to display and then the selection index path is how the outline view keeps its selection in sync with the tree controller and as I said we also have support for in its browser which has pretty much the same binding content and selection index paths and then also a Content values binding that you want to bind so that it'll actually get the value to display in the browser cell rather than just displaying the description of the content of any of the content object after that oh one thing if you go home and play with this tonight try and hook up the outline view to the pre controller and you go and start adding things adding nodes to your tree and start editing it editing isn't supported yet sorry that's coming but you can so you can still browse through the outline view and adjust the the layout of the tree that's still supported and the next major feature is filtering in the NS array controller we've added filtering directly to the NS array controller so you don't have to subclass anymore to get filtering support but in the process of adding filtering support to the array controller we figured we'd add filtering support to NS array and we've also improved the synergy of using the array controller with the search field and all that comes to us thanks to the NS predicates if you caught the core data talk earlier did anybody catch that talk yeah good good if with that with core data we get a new class the NS predicates basically it's a class that describes a condition and here the string representation of one of these predicates of a simple predicate it looks a lot like the condition statement of a sea-based language right so it's pretty easy to use it's really easy to work with and once you have a predicate you can filter an array get a filtered array from an unfiltered one using this method filter accusing predicate or filter a mutable array in place using filter using predicate and of course you can filter an NS array controller using set filter predicate once you have an array controller and you said it's filter predicate all of the arranged objects the objects returned from the arranged objects accessor of the array controller are the ones that match the condition defined in the filter predicate there's also a controller key for the fill for the filter predicate so you can bind objects that provide predicates to the Ray controller directly and because of the way the filtering works there might be strange user interaction it's for example someone has filtered out objects in a table view and they go and add a new object into the array controller pressing the little Add button and then it adds it but immediately filters it out that can be confusing to some users but and so we've added a new option to the array controller clears silt predicates on insertion with this option turned on which is by default the array controller will clear the filter predicates setting it to nil and then insert the new objects this should prevent a lot of confusion when inserting new objects by users and just to clarify remember that the arranged objects of the array controller is simply a filtered representation of the content of the array controller so don't worry about it deleting the objects from your underlying array 0 search fields so when we release cocoa bindings in Panther we had search field support in the form of a recent searches binding this gave you the ability to build search field menus excusing much like the one that you'll find in safari with Tiger we've added support for building search fields that look a lot like the one in mail so that you can select what you want to filter on and then the user can type in the search criteria and the filtering happens based on whether it's from or two or subject and it's pretty simple you simply bind the filter predicate bind the predicate from the search field to the filter predicate of the array controller and for every binding you make from the search field you get another menu in the resulting search field and again for every binding that you make for every menu item you have two options that you can set the NS display name binding option lets you set the name of the menu that'll show up in the search field so this way it's easy to localize your needs and then NS predicates format binding option gives you the gives you the ability to set the predicate format for that menu item so defining that the from menu item should search on the from category of your of your model objects oh we've also added some integration with core data speaking of and its predicate what we've done is added support for core data like functionality directly to the nsobject and NS array controller in in the form of well actually I'm getting ahead of myself I should talk to talk to you about core data first the idea behind core data is that you define a description of your data all the model objects of your application rather than writing all of the classes you define an entity so the entity has all the information that describes the model objects of your application with a description you can use an NS managed object context to manage managed objects there's a lot of management plan so with the managed object context though it'll manage all of your objects I guess that's really the only way to say it it'll try and keep a minimal set of objects that you're working with in memory so this is a good way to do like as needed faulting of your objects into memory space without you having to do much work and it also manages storage and retrieval of your data so it can handle saves and opens for you I think anyone who went to the core data talk who knows what I'm talking about so you don't have to write that extra code in your NS document subclass for for saving and and opening documents and the way the managed object context gets these objects and how you specify which objects to its advantage is by using a predicate the predicate simply defined for the managed object context which objects to fetch with these three items you can you can pretty much manage all of your model objects just through core data with a minimal amount of of code work and what we've done with the controller's is that the ability to define which entity the controller uses to which entity the controller manages really this is opposed to what is normally there which is the defining the object class now that you can define the entity you can also define a fetch predicate which is in this case different from the filter predicate of the array controller this is simply the predicate that the controller should use to fetch object and there's also a way of setting the bind setting the managed object context the controllers will fetch into you can do this either via binding or by an outlet in ib so with these three items with these three pieces of information the controllers can actually fetch for you through cord data just by knowing the entity what such predicates to apply for the fetch and which managed object context to fetch into you can even set the controllers to fetch automatically for you on nib instantiate or you can wire up an action from a button so that users can flick a little such button as much as they like and something to know when when you're executing a fetch from the that clock right when you're executing a set from the from the controller o into the object context sorry so when you're fetching normally it's possible to define not only a fetch predicate but also a sort ordering but once you have an array controller it's really better to sort in the UI that's always going to be more correct another thing is we've added a Content set binding for the array controller so that you can bind detail array controller like an array controller that manages the relationship from image object because managed objects in core data have relationships that are held in sets the array controller can't directly handled the relationship objects so we've added the content set finding and another cool side effect of key-value observing of building on those three kv blah technologies kb star technologies the key value observing the controllers are always in sync with what in the manage job context so you get all of that magic for free where if something is started into the context it's automatically propagated up to the UI at this point I think I want to do a demo and this for this I'd like demo to again sorry false signals ok so we'll toss out this simple example go to Xcode first all up demo the tree controller I have a simple app that I ripped off from one of my are borrowed from one of my co-workers and it's a file system browser no I should show you that I don't actually have much code in here as a couple of classes that actually represent the nodes and the nodes of the file system so these actually go out and get the information of the files in the file system and return it as a path component and my main controller really has not much in it oh let's do this oh yeah that's better so it's not much in there and again the node that's not much there beeping and so this is just a model object sort of thing the infosec and go back to the app so this is just an outline view bounce in the top to a tree controller and the browser bound for the same tree controller in the bottom as well as a text field that displays the selection so I can traverse through developer documentation and you can see that the outline view selection is being kept in sync with the the browser selection cool so that's pretty easy and for the for the filtering demo I was going to run one application but something's happened to it so I'll skip that demo I'll try and do something a little later if I of time so i'll just go back to the slides now ok so other new features we've done a couple of other things beyond just the core NS controller work we've also added a binding debug mode to help you guys debug the binding pro some binding problems you might run into pretty simple switch there's a default right and it's finding debug log level set that to one and any errors that the bind that the bindings encounter accessing or setting values or invoking methods will get logged for you defining what was bound and what the error was so you can track down if there were any configuration errors in your nib another thing we've added is info for binding this way you can get more information about a binding for any bound object so if you have a bound view the text field or something and you invoke in info for binding you'll get a dictionary back of information relating to a specific binding for that text field the dictionary has information like the object that it's bound to which is usually its NS controller as well as the observed key path so the key path that the view was bound with and also the options key gives you back a dictionary of options that the view is bound with more new things on the NS array controller if you've ever worked with the multiple values selection marker it's a cool thing if you select multiple objects in a tree controller in a an array controller for example and they all have the same name and you want to display the selection the name of the selection in the array controller the selection foxy the selection the object you get from asking the array controller for its selection can actually return either the multiple selections marker or the common name for the all the objects in the selection the way it does this is run through all of the selected objects and compares whatever you're going to display for those objects so if they all have the same name then we'll display the name otherwise we display the multiple selection marker placeholder this might be a little bit more information than you need but the point is now there's a new option to turn off that behavior so that anytime that there's more than one item selected will always return the multiple selection placeholder the selection marker so this can be a big awesome ization for selections that are very large where all the names might be similar well the values might be similar and we rather do we have other random options and bindings that we've added and it's view now has a tool tip binding and as text view as an attributed string binding so now you don't have to convert from RTF data blah to get attributed strings into your text field your text views and this window now has a display pattern title binding so you can customize the display of the window based on multiple pieces of input from the controller's the table column now has a new option for turning off automatic creation of the sort descriptors we automatically create sort descriptors for all the table columns in your table that way you get sorting for free some people don't like that so now you can turn that off and as I said we have a new new binding for the array controller content set for working with the managed objects relationships we've also added some changes through the way and it's pop-up button and NS matrix work specifically we've added content objects as a new binding with content objects you can imagine if you bind all of the if you bind the pop-up button to an array of objects as its content and you want to get you want to synchronize the selected objects of the pop-up button normally you would get back in that selected objects array all of the objects that are selected from the content array but you might actually be more interested in objects related to the objects in the content array so now with content objects you can define for example the name of all the people in the name of the people that you're displaying at the pop-up will come the selected object so you can target a different object in your in your pop-up it's really simpler to use and to explain sorry and its matrix this is pretty simple and its matrix has two modes that we support three modes really in radio mode the default we support single selection so there are two bindings the selected value and the selected object when the matrix is in list or highlight mode we now support multiple selection so that you have the selected values and selected objects bindings available this is the simply change that we had from last choice oh right new features that's it now I've been to some of the tips and tricks for building Coco friendliness into your own classes if you have model objects that you want to use with Coco binding you're probably done that's usually that's all you need to do as long as the attributes that you expect to be bindable our key value key value coding compliant so in other words your other words you have either a key value coding compliant accessor or the attribute where you allow direct I've are accessed usually that's all you really need to do and part of that is that key value observing automatically sends out notifications that that Coco bindings requires as long as you're the the attributes that you're exposing is bindable our key value coding compliant key value observing does the notification generation for you if we're if for some reason you have other attributes that you want to expose as bindable that aren't key value coding compliant where you have some really complex logic that changes lots of values lots of lots of attributes of your model object all at once then you can send out notifications manually simply invoke self will change value for key pass defining the key passes is about to change change the value related to that keep up and then invoke self did change key path this is the way that you send out key value observed notifications manually so as long as your object is key value observing compliance and you have some key values coding compliant way of getting to the values the next thing you would need to do actually this is on the wrong side key value binding exposing should be on this slide if you if you have a view that you want people to be able to bind um in order so that it has those neat little attribute boxes show up in interface builder all you need to do is let me go back pretend that that last those last two items are on the next slide exposed binding and exposed bindings are two methods that you can that you can use on your class they're defined in key value binding H and it lets you programmatically expose bindings for your class that way they show up in interface builder as long as the class is loaded by a bundle or a pallet continuing with making your view cocoa bindings compliant once you've exposed the binding of your view you'll need to implement the bind to and unbind methods the bun to method is how is is how you get the information of of what your binding should do of what's the synchronized between your view and some controller object typically there you would simply cash the object your binding to as well as the key path and options dictionary that you're going to be that you're creating the binding with and immediately after you would typically add yourself as the observer of the object you're being bound to so your view would invoke self add observer or object that you're biting to add observer self so that way notifications in the form of observed value for key pass whenever something in the observed object changes once you have that in place if you have a view that's actually doing something that's editing related editing a value rather than just display you'll probably also want to implement the NS editor and NS editor registration methods well really implements the NF sedative methods and know about the NS editor registration methods NS editor is a proto informal protocol that defines how the controller can tell your view that it should stop editing or discard editing commit editing is invoked on your view if you should try and end editing in your in your view and then you can return succeeded or oh if there was some sort of verification validation error discard editing is since when you should just throw out any changes that the user is made and revert to previous value once you start editing once an editing session has started like the user has started moving around something in your view in your control then you can invoke objects did begin editing on the controller that you're bound to this you should be notified if committed if it should commit edits or discard any edits and that's course once editing is done you can send the controller objected and editing now once we have your view and it's bindable and beautiful then you should really put it on a pallet that's the best way to take advantage of cocoa binding so that people who use your view use your code don't have to write the manual bind to blah blah blah message in there in there in there classes now just going over again some of some of the basics of how cocoa binding works with key belly coding observing and binding when I say a key value coding compliant access ER I'm really talking about a name and set name kind of method pair with that your your model object will be key building key value coding compliance for the key name so that way you can bind the some attribute to an object that is of your object type with the keepass name that's all you need to know for them oh oh that's true now if you're a view and you want to implement this bind method again what you typically do in your implementation is cash away the observed controller the key path and the binding options that are sent in during the binding creation and if you're going to support more than one binding it's probably a good idea to cash these in a dictionary on a binding basis this way when you get the key value observe observe value for key best method method invoked on your on your view you can keep track of what attribute you're supposed to update in your view and here I'd like to ask andreas to come up to do a little demo he doesn't know what I'm getting him into so I think a lot of people are kind of confused about how cocoa bindings works how to bind to method works so perfect so if we pretend that you guys are the developer of some application and I love you and Andreas is a controller not that I'm saying anything here in order for me to keep some attributes say my I'd wanted to find a hat actually say which arm is up if I wanted to keep that and think with some value that andreas can give me exactly see all you have to do is say Ron bind arm height to andreas Ron bind arm height to Andre perfect so it's something like that so now anything on dreis does I can see and update my state pretty that it's pretty simple right see now now the great thing is the great thing is we with bindings you can also add value transformers so that anything that I get from the controller can be changed before actually sent to the view so if there was an NF negate boolean transformer or negate arm high transformer anything he did would be in reverse not done with you yet so let's do a little role reversal is my therapist before my face let's pretend that I'm the controller and that andreas is the view what really happens is if something changes that in some model object somewhere then I would send a notification Andre and what this really highlights is not only that the notification is really lightweight let's it could so lightweight could you can get that we can send a lot really fast so this is this is how you should think about Coca binding well maybe not but so you get the idea hopefully that clears up exactly exactly what's going on when you bind objects find a view to another object and with that I think oh now quick recap yeah yeah there we go so Model View controller again model view controller that's what we're based on Coco lives and breathes Model Model View controller because of the code reuse that's really what we get out of Model View controller here and with Coco bindings now we get a set of reusable controller objects as well as the notion of bindings so that we can we can cut out all the glue code that were used to write in and to to keep with the the outline that I introduced some of the new features we've added to Coco bindings includes a tree controller so now you have something to bind to from the outline view in the browser we've also added filtering directly to the array controller also to NS array and NS mutable array we've even added core data supports the controllers so that you can fetch directly into controllers and then we've added some new bindings and bindings options which you'll see the documentation forthcoming one more and so the tips and tricks for for rolling your own bindings come down to making sure that your model object and your view objects are key value coding key value observing and key value binding friendly this means making sure that all of your model objects have actual KBC accessors that and and that you can do the key value observing notifications and then for your view classes it really helps to to expose the bindings of any attributes you want and then put that view on a pallet and with that here's all the reference stuff and who to contact would be Matt Formica will be coming up shortly I believe
