WWDC2004 Session 436

Transcript

Kind: captions Language: en welcome to session 436 advanced core data features like the slide said this is a confidential session so please retain frein from taking pictures camera phones filming microphones that kind of stuff I am Melissa Turner I'll be joined on stage later by some of my co-conspirators in the code that we're about to show you Ben Trumbull and Chris Hanson so what is core data for those of you who didn't make yesterday's session core data is a model driven object graph management and persistency framework what does that mean basically it's a framework that gives you scalable object lifecycle management tracks on doesn't gives you automatic undo redo chain tracks changes in your object graph I suppose I should say at this point object graph is a fancy way for saying collection of objects that actually have pointers to each other gives you introduced data consistency and correctness in the persistence part will allow you to read or write to various types of files and we're integrated with the cocoa bindings to give you user interface synchronization why should you use core data well it relieves you from having to reinvent the wheel there's a lot of persistence frameworks out there I'm sure many of you have actually written one you don't need to redo it over and over again there's nothing terribly tap app specific about it we give you a choice of persistent stores so you can pick the one that best suits the type of application you're writing one of the big advantages is it prefers your application for future features in cocoa if we're going to add new stuff it's most likely going to be tied in with the stuff we've already written so if you're using the stuff we've already written we'll probably get those new features for free gives you a faster development life cycle writing an object graph management or persistence framework is not a simple thing trust us we've been working on it for months we'd like to spare you that and let you concentrate on writing the stuff you want to write and because it's there it's used by a number of other people it's a lot more likely to be robust people are gonna find the bugs you don't have to do it yourself in this session we're going to sort of give you an overview of the architecture of the system talk about the individual components we're gonna talk about how they're all put together we're gonna talk about some of the stuff you want to do or if you're advanced you're gonna want to deal with the stack and we're gonna give you a few as we go through tips and tricks things you should know things you should know not to do so what are the pieces of the core data architecture well we're built for there's four basic components there's predicates models managed objects in the managed object context and there's object stores of the store coordinator and like I said we have some integration with the cocoa documents and controllers core data Xcode UI can be used to graphically create how the models for and configure how core data is going to work in your application here's the basic architecture up at the top which we're not going to talk about in this session is the user interface which is connected with the binding stuff below that we've got the controller layer again we're not going to talk much about that middle parts where we start getting interesting that's the managed object context that is sort of the core of the object graph management part of the system it manages the manage objects we've got a persistent store coordinator living below that which talks to a model and a data file well I've mentioned model several times there's sort of the really most important part of the system there the blueprint there the thing that describes what data exists in your application and how those objects are related to each other tells you what interactions you've got going what needs to be updated if something else is updated all that kind of stuff the model is really sort of the description it it contains all the really important application logic of your system it's the foundation for manage objects and you can create it from Xcode or programmatically Xcode gives you the basic development tools the thing you use up front it's nice it's spiffy it's graph graphical it's visual you can see what you're actually doing often that's not quite enough and you want to make some minor run I'm tweaks to the model so we let you to create a programmatically or modify them programmatically if you've already created them why do we use a model it's a foundation for data-driven development what that means is you can concentrate on the data architecture of your application rather than the control flow through it you think about what objects you have how they interact with each other as opposed to well if I click this button here then I need to do this in this object and if that then or while don't need to think of any of that you just concentrate on the objects we take care of the rest of it the model as I said defines this data architecture and what this allows you to do if some of you saw in yesterday's session orbit Ron's keynote is get behavior without writing code what's in a model some of these terms are going to be familiar to those of you who are familiar with entity relationship modeling but a model contains entities which have attributes relationships and fetched properties it also contains templates of fetch requests which will you will talk about all of this later and it contains configuration information this is the classes these things map to this is what you should be looking for in the API headers you got on desk Anthony's mapped instances of innocent any description attributes to NS attribute description relationships are in its relationship description fetched properties or NS fetched property and festro crutch templates are NS fetch requests configurations well those are just strings usually with sets associated with them in a sense any description is loosely analogous to class definition for data type it supports inheritance which means you can have abstract entities things that never never actually instantiated in your application Anthony inheritance is not necessary analogous to or is not necessarily the same as class inheritance you can have an in Antony inheritance hierarchy that does not map one to one with a class inheritance hierarchy as a matter of fact you can map everything to NS magic managed object if you want and skip having a hierarchy entirely has multiple property types the two most important of which are attributes and relationships and their entity editable only until first use this is something important to remember once you fetch data into an application using a necessity the description you can no longer change that and ascend a new description it gets too complicated trying to figure out what we're supposed to do with that extra pieces of data and new stuff old stuff can't do it you'll basically have exceptions thrown and by the way that's true of all the classes I'm going to talk about in the model section an ass attribute description is analogous to a field containing an NS value type we support all the standard NS value types or standard NS data value types you can set a provide a default value using an NS attribute description and you can set validation rules this attribute has a minimum value of this has a maximum value of that must have four strings can have set a wildcard of pattern set a maximum string length that kind of thing attributes can be optional which means they don't necessarily have to appear and they can be transient which is a concept that makes a lot more sense when you think about it in the context of there being a persistent layer but a transient attribute is one which is managed by the object graph management layer but which is not actually persistent this is the kind of attribute you'd use for storing caching information stuff that's derived at runtime and can be recomputed but you just want to keep around for you know convenience and speed purposes it's pretty much a scratchpad relation just descriptions relationship descriptions well those are pointers to another antman pointers to one or more managed objects they can be one-to-one they can be one-to-many they support minimum and maximum counts this bicycle has two wheels this vehicle has at most 18 wheels you can specify both of these values a relationship usually defines an inverse relationship there's some rare contexts in which it doesn't and if you don't know the specifics you want to define a inverse relationship it specifies the delete rule what should happen when an object is deleted the options are nullified when this object is deleted delete all of its delete the objects in all of its relationships cascade now nullify is when this object is deleted just null out the back pointers in all of the relationships cascade is delete all of the children its relationships deny if this object has any objects in its relationships you're not allowed to delete it no action means don't bother touching anything on the other end of the relationships it also allows validation rules like the attributes and like the attributes it can be optional or it can be transient and as fetched properties kind of a special beast it allows you to make a unidirectional link between an entity and a query this allows a single managed object to have a loose relationship with a collection of other objects and that relationship is not managed it's always too many because we can never tell how many objects the fetch is going to bring back and it uses an NFS require NS fetch request which we'll talk about next to specify the query the concepts of optional and transient don't really apply here since well its query NS fetch request is an object-oriented representation of a query operation specifies a query that you want to search for an entity that you want to search for a predicate that you're going to use to define which instances of that entity you're looking for a sort descriptor that tells you what order you want them to come back in fetch requests in the model are named templates which means that they contain predicates that can have variable expressions in them if it has a very expression you need to do a variable substitution at runtime before you use it and you get an instance of a fetch request from the template from the model using fetch request from template with name set substitution variables and one thing to note is that these fetch quests the predicates will be evaluated in the store where possible so if you have an SQLite store the predicate will actually be translated down into a where clause which SQL light will actually run some of the other stores actually do in memory queries a configuration is essentially a named collection of Ventus NS entity descriptions it's typically mapped to a single persistent store this collection of entities is mapped to this store this other collection of entities is mapped to this store something to note is that a single entity can be belong to multiple configurations so you can get instances manage objects of a given entity from multiple stores I can pull an address from LDAP or from address book I can get a song in my playlist from my local repository or it can be something I pulled from a rendez-vous store problematic interaction with models is actually pretty simple if you want to load a model we have NS magic managed object model init with contents of URL sometimes you want to merge multiple models that exist in multiple frameworks we have init with contents of URL and then model by merging models something to note is that this will get a little bit upset if you have multiple entities with the same name but multiple if you have configurations with the same name in each model the entities in those configurations will be merged into one uber configuration programmatically creating a model is very simple it just takes a lot of steps first thing you're going to want to do probably is create an entity description here we're creating an album you set the name on it to album most albums have attributes so we're going to give this one a title just create an attribute description set its name to title set its type to string create a song since albums usually have songs it's another entity just give it a name create a relationship songs has the entity it comes from the entity album and sets the distant destination entity songs this means that we're creating a relationship from the album two songs a song has an album has multiple songs set the relationship set the properties on the album set the entities in the model and now you've got a really simple model has two entities couple of attributes doesn't do much and it's actually a lot of code even though none of it's terribly complicated so we're going to bring Chris Hanson up on stage to show you why it's not actually as scary as you might think it is can we go to demo one can we go to them there we go thanks Melissa so what I'm going to show you is a conversion of an existing application an existing cocoa document based application to use core data I'm going to show you how it's actually pretty easy to take your existing software and bring it forward to the new world so I have a lot of books and I like to lend them to my friends but I need to keep track of what I lend because otherwise I'll just forget and then my library looks smaller so I have this little lending library application as soon as X comes up here and it's very simple I'll just start it building now and walk through the code it's a simple cook of document based application that has just a couple of very simple model objects book and friend and the document itself persists using data representation of type and loaded load data representation of type just using an S key to archiving bigger font size got it text editing yeah I can yeah sorry about that syntax coloring Monaco why don't we say 14 bigger than that bigger okay how's 18 there we go so it's persistence is really simple right now we're just adding a couple blue you know we're just adding our objects are two arrays of books and friends to a dictionary and then writing that dictionary out using key to archiving the first step in bringing this forward is of course to duplicate the project so I'll just make a copy of this and open up the new project and then I need to actually make a model for core data to work from so what I'm going to do is add a new group called models and then add a new file to that group and that new file is going to be a court is going to be a design data model I'm just going to name it blending library and here I get to pick classes to add to that model so I'm just going to pick a book and friend and add all the classes that are in those header files and I get a model and if I show the class browser here I just are the model browser I just went to design shows show model browser and let's see I'll kick this up for you too we can see that it picked up the actual types of the attributes and even the type of the relationship by picking the destination however that relationship is named to friend and in the actual file here it's called went to so I'm just going to go back here and I'm going to change this to went to now I actually yeah we all could we also can see that here it's actually set the class name the class names appropriately so these model objects will be backed up by instances of these classes however right now these classes just descend from nsobject and implement NS coding since core data is going to manage all of our persistence and all of our change tracking for us we don't really wanted to send for a menace object anymore we wanted to send from and this managed object and since managed object handles all of our persistence for us we don't need to use honest coding anymore either so we can actually get rid of these attributes and we can even get rid of this relationship I'm going to get rid of a couple of accessories and I can even get rid of that relationship accessor because everything in our interface is going to be done through bindings and key value coding now I can also get rid of my D Alec method because I have no more storage to manage myself core data manage does all that for you I'm going to convert my set author method to show you how you might want to do this in your own applications to use what we call primitive key value coding so the first thing I need to do is in set author I need to inform the rest of the system that we're going to change the object so I'm going to just say self will change value for key of author then I'm going to actually do a self set primitive didn't complete for me set primitive value for key will actually call into our superclass implementation which manages all the storage for us and do the right thing for both attributes and relationships it checks against the entity and finally I'm going to tell the system that we did change the value for key and this way if you if your application uses your accessor methods you don't have to get rid of them and just go through key value coding you can still use your accessor methods you can just make them a lot simpler and act as covers for primitive kvc and i need to do the same thing in author i just need to say a string author self will access value for key this tells the framework that we're going to start accessing that key so if it needs to pull anything into memory if it needs to fire any faults that will happen then we say author equals self primitive value for key to actually get the data then we say self did access value for key there's a lot of symmetry in this framework and finally we return the value that we were retrieved but if you're just using key value coding key value coding will do all of this for you so you don't need to actually even have these accessories your entire interface is built through bindings and you're using key value coding you're fine and this works both for attributes and for relationships and finally we also don't need our NS coding support anymore because all of our persistence is being handled by core data and we can do the same thing to our friend object we can just convert its superclass get rid of its aivars get rid of its successors and well let's see pretty much get rid of all the code in it now we only have a couple more things to do I think three more things first we need since core data is managing our persistence we can also get rid of the instance variables that we're using to store our collections of books and Friends in our document we just need to tell it that it's not an S document anymore it's an NS persistent document we don't need these anymore because everything is going to be accessed via key value coding and same with these and of course we can delete the implementations too we don't need to actually handle our own persistence anymore so we can delete these and finally since we're not handling anymore management we don't have any more aivars to memory manage we can delete in it in d Alok - so this is our new document subclass and now we only have two more steps our first step is to go in and change the type of document that we handle right now I'm just handling a document type of lending Lib I'm going to change that to XML so so core data knows to use the XML persistence and then I'm going to go and make a couple minor modifications to my nib file our nib file still has some knowledge about the classes that we were using and we need to update it so our nib file is very simple it's just a simple two tab interface with a couple of table views all set up using bindings this application would run fine on Panther before moving it to core data we don't actually need to do anything with the table views all we need to do is modify our array controllers so our array controllers right now point to a class and a class name we're going to change them to point to an entity and an entity name so friends points to the friend entity and books points to the book entity and then we're going to set one additional binding on each of the array controllers this binding well and we're gonna remove the content array binding because we're not actually getting the content from the document anymore instead we're going to connect the binding on each of the array controllers for its managed object context and that comes from our document every persistent document has a managed object context and actually also has its own persistentstorecoordinator so that handles all of your change tracking for you automatically so I just did that for books let me go do that for friends actually yeah just object context find get rid of content array save and we're set so now I'll just build and run this one actually while I'm building this I'll run the original and as you can see it's just a very simple you know document based app can add an author of a book I have you know say John Brunner the shockwave rider I can add another book that I have Douglas Adams The Hitchhiker's Guide and I can add a couple of my friends Ben and their phone numbers in case I need to contact them because I need a book back really quickly and Melissa these aren't their real phone numbers don't try them and I can see that in my lent to pop up I can set oh well I went Ben the shockwave rider and I like Melissa Hitchhiker's Guide to the galaxy and notice what we don't get um if I add another book say uh weinberger the Cluetrain manifesto and I want to undo that I can undo the typing in there because that's handled by the text subsystem but I can't undo anything in the actual document because I haven't written any undo code for this application but this is the old version notice also that I don't get any document dirty again I would have had to write code for that I still can save and load documents though but let's check the new version if I run this I can start out I can say John Brunner the shockwave rider and say Douglas Adams Hitchhiker's Guide I can see that you know I get all the same tableview behaviors I haven't touched this part of the interface there's no value for these pop-up menus because I haven't added any friends yet I can add a couple of friends and they show up in the popups and all of this all of this relationship management all of this while all of the persistence that's gonna happen when I hit save is going to be handled by core data but notice what we also got we also got dirtying the document is now marked as modified so if I just try to close it it automatically comes up and asked me if I want to save so I'm just gonna save this on the desktop I'll just call it my brick my library I quit it I rerun the app I choose open I go to the desktop I open that up and everything's in there so it's just round trip through course through core data now I'm going to try adding a Weinberger's book again Weinberger the new train manifesto but I lost that book it's not in my library anymore so I'm just gonna undo I can undo that and I can undo that and then I can go up here and I can see oh I can redo those insertions so I just redid the add of that record and I redid the update of that record and now I redid the update of that record and that all came for free just by using core data so now I'm gonna turn it over to Ben is going to tell you a little bit more great good morning my name is Ben Trumbull and I'm one of the senior engineers with Chris Melissa in the development technologies group at Apple and I'm going to talk to you today about the two classes that you'll probably interact with the most and the core data framework and the first is ns-managed object if you take something away from the session if you're looking for a noun to work with from core data you'll probably find it here so andis magic objects are instances of an entity and they always have an energy description in the same way that a cocoa object always has a class so it's the data equivalent their generic data object so as Chris showed you you don't need to use storage you can just have it go through and magically will manage the memory for you you can use key value coding to access those fields and get back the values it's a basic unit that you're going to be working with these are the objects that you push around you fetch insert change save etc and they all implement key value coding and key value observing for you fundamentals is each instance is described by a single entity and has a reference to it each one has a unique object ID and each one is associated with a single managed object context which we'll get more to later it's important to note that each managed object can only be used by a single managed object context at a time and subclasses can implement custom logic as you saw in the demo the did a lot of times you don't really need any custom logic in your subclasses you don't have to have the subclass all right you can just say in your nib or whatnot that you're gonna use the entity and will automatically just use the generic superclass and it'll get all the behavior for you as long as you don't need any accessors or anything customer so to take a brief tangent it's interesting to note that the IDS that are unique for each managed object are objects in and of themselves and they're an instance of NS magic managed object ID and one useful feature of this is that different managed objects with the same ID refer to the same persistent data so if you have two objects and they have equivalent object IDs then they refer to the same XML note in an XML file or the same row in an SQLite database so one of the things that you can implement either in the model or in a subclass is validation and the managed objects do validation upon themselves these validation callbacks are invoked at save time so you'll get a callback for deletion insertion or updates and you can also validate on individual properties I have lost my formatting but at the very bottom there you'll see validate key and key here is not the method name but the name of the property validating so in the previous example you might have validate book or validate friend and you can just go through and your subclass to validate an individual property other useful manners object callbacks are awake from fetch an awake from insert here's a great place for you to initialize transient properties or to set up any caches or do any calculations that you want to set aside for the object and two other callbacks for you or will save and did save and a subclass can do something interesting here the awake methods are generally more useful just to set up initialization so to talk a little bit more about primitive key value coding these are the methods you use to implement custom accessors setters and getters there's a primitive value for key and a set primitive value for key they're only for your use in the implementation of an access or method the framework uses to do low-level initialization to do bit shuffling and stuff like that they don't go through the regular key value coding and they don't perform any kind of validation any kind of argument checking they assume you kind of know what you're doing so they're fairly low-level and they don't manage any of the integrity for relationships to create a manager object typically you'll just do a fetch as you saw in Chris's example when he opened up the document they just come up for you and they're automatically created for you and registered with their context if you want to create a new one you just a lock insert with entity and give it an entity and after that you pass it to its context and you say insert object one other thing you can do is if you decide to use core data without it's in native persistence mechanism you can use your own persistence mechanism or use the NS coding behavior you already have and just use the context to do change tracking and do the undo redo and you can do the saving yourself in this case you can use registered object to tell the context this isn't a new object it doesn't need to be inserted into the data file you've pulled it off from some other data source somewhere and you just want it to know about the object to track changes okay so the NS managed objects have all the nouns they have the entity description they have the object ID they have all the data from the data store the verbs live here in the ns-managed object context so this section a lot goes on here so we have the little preview so we're going to talk about fundamentals I have a slide on fetching inserting deleting updating saving reverting notifications memory management and threading like I said a lot of verbs with the managed object context so this is the primary center of the framework for your use it initiates all the actions and it does all the heavy lifting for the change tracking it performs retrieval the objects from the external store it does the saving and the reverting of changes it implements undo and redo it propagates the deletes and maintains the inverses and the exact behavior of the delete propagation and whatnot based on what you've set in your model in the NA description and it also is involved at the center of all the activities so it's the one that posted notifications and does the callbacks for fetching it's a little small but there's an execute fetch request method and you just passed it a fetch request and the managed object context goes off and figures out who to pass that request to to have it fulfilled the only mandatory part of a fetch request is the entity and everything else will do a useful default one important feature to note is that the context will merge in changes that are pending that haven't been saved that into the results of the fetch so if you have a bunch of inserted objects and a bunch of deleted objects and you execute a fetch if the predicate that describes the search you're doing matches the insert objects those will get included in the results you get back and the deleted object will be excluded and change objects will be included if they match but if you change an object so it's no longer true when it evaluates for the predicate then it will be excluded as well and you can always create a new managed context and do the fetch directly with that or you can do a reset so walk through a little bit the fetch control flow in this diagram here a is the fetch request turns out graphic artists are very very literal so yes so you create the you create the fetch request and you pass it to the ns-managed object context it takes the fetch request it does some work with it and then it passes it to its persistentstorecoordinator then the persistentstorecoordinator figures out which objects stores have the relevant data and passes it off so you can have multiple stores you'll get back some results each of the stores does the fetch with its own native mechanism whether it's an SQL query for SQL Lite or walking through the XML for an XML file and then the results come back and they get collated and brings them back and they're sorted and the ns-managed object context merges in the change set so the fetch accurately reflects what it knows as the state of the world okay so we've talked a little bit about inserting all you do is invoke insert object with your new managed object that you Alec and hit it with entity it's best to define the initial values after you've performed the insertion the reason for this is context only track changes after it they know about objects and they only know about objects after you've called insert object or register object and you won't get the correct undo redo behavior if you set a whole bunch of initial values and then you insert it because the manager object context will assume that that was the initial state so as you saw in the demo you can undo the text edit that way and when you're done you'll just have a blank row deleting an object you just pass the manage object to delete object on the context the deletes will be propagated through the relationship that incident through the relationships that that object has and the exact behavior will depend on which delete rule you've set also talked about the different delete rules nullify cascade deny or no action it's important to note that if you use no action this means you have assumed responsibility for maintaining the integrity of those relationships so if you've got objects with pointers to each other and you say no action when you delete one you're gonna get dangling pointers and you've promised that you will clean that up another important thing to note is just because you've deleted an object it's pending this doesn't take effect until you save so this is a perfectly good object you can keep working with it asking for data it's valid and you can undo the delete so it's really a pending of a delete a lot of things happen when the objects change and this is really an overview of what's going on behind the scenes you don't really have to worry much about this but this is what the context is doing for you you keep value coding observation notification gets posted by the object itself and the managed object context receives an internal call back at this time if it's necessary it takes a snapshot of that object so we can maintain the correct under redo behavior and then it makes sure that the bi-directional relationships are maintained and it Flags the object is updated and cues it up it also queues up and end of event notification so it tries to minimize the amount of work it does for each change so if you do a whole bunch of sets with key value coding or with an axis or method doesn't want to take up too much time and it will coalesce things later at the end of the event so at the end of the run loop we get our callback back to ourselves we coalesce all the changes together we push an action a single action for each object onto the undo manager stack and we pass up a notification for you if you want to know about it and that's the point where the bindings receive some of the notifications and it's one of the points of integration with the cocoa bindings for saving changes there's just a save method you can pass in an NS error if you want to find out what happens when things go wrong if things go wrong and this is the same control flow as to fetch except you don't get any results back we group all the insertions together and the deletions and the updates we pass it to the president's store coordinator and if this is the store core now figures out where everything goes and then each store writes it out so reverting changes you can use the rollback method this just does a simple revert and restores all the objects to their state before they were sorry so the same state they had when they were last saved so this will throw away insertions it'll undo changes and deleted objects will now go back to their previous normal State you know us and doing a reset so the reset will basically take this context and flush it and restore it to its initial state it'll forget about all the objects at scene and you can just reuse it this is useful if the context belongs to something else like the nib and you don't want to replace it with a new one but it's a similar effect to just creating a new one and it also has the undo and redo methods these use the NS undo manager you can get a hold of managed object context undo manager and customize its own behavior like set levels of undo or throw away all the actions remove all actions so it's just integration with the default foundation on this undo manager notifications the one that's most useful is the first one the objects changed in managing context and this happens at the end of the event after we've done all the changes and we've coalesced everything together you can find out what other people have done to your soup of objects then when you do a save after the save operations successful we post this notification the management context did Save Changes notification and that might be useful if you want to know who's been committing changes to the file the user info dictionary has the same structure for both these notifications there's an inserted key lowercase I updated and deleted keys and both these keys mapped to a value which is an NS set and the set contains all the managed objects that are inserted updated deleted and it's also important to note that the manage objects themselves individually post key value observing notifications with the normal foundation mechanism so just a brief overview on this we touched briefly in the demo about faulting and why you have to call will access or will change followed by did access ur did change and that's that we can do faulting where we basically prune objects that you're not using and then if there's a relationship and you want to do something would go and we'll fetch it for you to try to reduce the amount of stuff you have in memory this is particularly slow the SQLite database so this is analogous to kind of virtual memory so it's that kind of faulting when we talk about faulting it's at a higher level than page faulting but it's basically the same the same since to there you don't really have to worry about it it's fairly transparent you touch something and we'll bring it into memory and then core data for the most part is a big cache of things and faulting is adding or replacing the cache lines so you're working set is mostly the changed objects and you may have fetched other objects to work with them whatnot but once you're done with them then we're gonna keep little shells of them around but we don't need all the data because it's still there and this could probably be a session in its own right so I'm not gonna say much about it so I don't say anything wrong but locking and unlocking the managed object context is pretty useful it implements an NS recursive lock so you can use that way but it's not just for thread safety it's important to signal to the framework that you're using this context and it's basically wrapping a transaction so this prevents other spreads from interspersing their changes mixing up the undo stack or you save a bunch of threads changes together this is why it's not enough to just lock in between an insert operation and then unlock after the insert operation you want to group a whole bunch of things together and this is how you do that it also prevents the framework from you processing notifications that might interrupt your state so basically it's a signal that you're using this managed object context and then you unlock it when you're done with your transaction great and now most it's gonna come on and she's going to tell you about the rest of the framework underneath it just pretty quick section to wrap up on thank you thanks Ben so the stuff Ben and I have talked about so far is pretty much the stuff you're most likely to have to interact with but there are lower levels in this framework and this is sort of a quick overview for those who like to know how things work you probably won't have to do much coding at this level but if you do or if you're just curious this is how it works each managed object context has a persistent store coordinator persistent store coordinator is pretty much the bridge between the object lifecycle management part of our stack and the persistence mechanisms in many ways it's like the managed object context and the magic objects are the center of your world the persistent store coordinator is the center of the frameworks world you have one persistent store coordinator per stack and only one but you can have many contexts you can have many stores using that persistent store coordinator it's really the thing in the middle that does well coordination the really important part about it is that it provides a facade of a single object stored managed object context the managed object context knows that it has to talk to one thing doesn't care what that thing is it has to talk to one thing and we initialize it with a managed object model that's important because this is where the managed object context and the underlying stores get their model I mentioned that if persistent store coordinator can have multiple stores object stores are things you interact with in this release only through the NS persistent store coordinator but so you know the the actual persist to backing store mechanism we have three stores that we provide this release XML SQLite and binary each store type has its own advantages and disadvantages and you can move data between stores transparently or almost transparently they said we provide three stores in they each have advantages and disadvantages vinery store is fast but it only operates on the whole object graph your entire collection of objects that you're persisting comes into memory and is saved as one unit this is fine if you've got a small application but can get unwieldy if you know you've got something with thousands or hundreds of thousands of objects the XML file is very much like in the binary object store only it's XML it's bit slower but it is externally possible so if you're building an application whose data you want to share with other applications this might be the way you want to go and then we have the SQLite store this is scalable it's are easily the fastest store and most importantly it gives you the partial object graph management this is the only one of the stores that gives you faulting out of the out of the box you don't need to worry about which objects get read into memory as long as you're doing the will read will access and did access methods the object graph management context will take care of pulling everything in and out of the SQLite store for you so now we're going to talk a little bit about how you initialize a stack it's actually that covers most of what you need to know you create the URL for the location of where you're going to find your model and create a model initialize the persistent store coordinator with the model tell the persistent store coordinator add persistent store with type in this case we're using an NS XML store and the URL where you want that data to be stored we create a managed object context and set its persistent store coordinator at this point you have a stack that's fully ready to have managed objects pushed into it managed objects pulled out of it of course as Chris showed you in the demo earlier that's how much initialization you've got to do if you're using a document based application we dodo for you [Applause] some more details about working with stores yeah there's a few other things you might want to do here we're doing the same kind of creation and adding of a store that we did in the previous slide but we're also showing you how to migrate it's pretty simple create a URL and add the telephone system store coordinator to migrate data from store one to another store created at that new URL once you've done that you might want to remove the old star again it's simple tell the persistent store coordinator to remove it but once you've done that it's really important for you to do this you have to reset the managed object context object graphs can be complicated and if you you know remove a store you've essentially removed the underlying backing for a part of your context you need to reset the context so that all the objects that were in that store will get flushed out don't forget if you see confusing behavior you might have forgotten now we're going to bring Chris back up and he's going to show you a demo of how you can use the core data frameworks to stripe objects across multiple stores thanks Melissa I just like to point out one other thing with the document based application that I showed in here I forgot to mention that we don't implement any storage methods but if you have a legacy application that already has a file format you can override sort of the the main entry points for the document loading and saving and still handle your own file format so you can just get those you know get objects into memory from your file format and insert them into your documents context and then use personally you know use core data to save them out again but here I've built a little application for looking at the WWDC schedule I just grabbed something I just got an XML version of the schedule for a couple of days and I actually built just a standard cocoa application I didn't build a core document a core data application so I just created a basic application delegate just like you would see in any cocoa example and and it's an it method for when it's instantiating them in the nib file I have the initialization of its mom it's a managed object model it's persistent store coordinator and a managed object context to use for the application so here I'm just getting a model from our bundle or getting the path to a model from our bundle I'm actually instantiating that model I'm creating a persistent store coordinator that refers to that model and finally I'm creating managed object context that is attached to that persistent store coordinator and let's start this building and running now here I just have a basic table view all done with bindings and I have a button this button has one action method and that action method is attached is add store and what this does is it brings up an open panel and grabs the store from a file and adds it so I can go in here I can pick Monday's schedule and I see all the sessions that were on Monday and their day and time and the room they were in but notice that this is fairly generic I just get the first URL that I've selected in my open panel and add it this mean oh and then I tell my array controller that's connected to the table view to fetch and the new fetch method on a rate controller will actually go out to its managed object context and run a fetch so if I click Add store again it goes through the same steps and I can pick Tuesday schedule and Tuesday's schedule shows up in my table view but if I sort this by day in time I see that Tuesday's sessions were added to Monday's sessions this is actually I'm an object continum one managed object context connected to one persistentstorecoordinator that's now connected to two stores both of these are XML stores but they don't have to be one could be an XML store and one could be an SQL store and that's it this is a very simple code barely any in fact and it lets you work with multiple stores all from one context so I guess I'm going back to Melissa there's some random other stuff didn't really fit anywhere else in the presentation so this is the other stuff section we've mentioned Chris mentioned during the demo and it's sort of been alluded to a few other times we have a NS persistent document subclass of NS that integrates with the core database persistence and object management stuff automatically you don't need to think about it just create it we do everything else for you it's got full undo redo support document they're young and it does provide hooks for configuring the stack if you want to do something special if you want to create a document based application using models from multiple frameworks we provide hooks that let you do that we've got as we said cocoa bindings integration the big takeaway message here's it just works managed object can be bound like any other object that supports key value coding you get undo managed undo redo support through the context and as you saw in Chris's demo the controllers are now model aware so you can drive it all using the models and the array controller actually has a field that will allow you to configure a fetch an NS fetch request to fetch context from the object context so if you want an array controller that only contains a subset of the objects in your context you can build an NS predicate that fetches only those objects well that's actually about all we've got to talk about you're gonna get in the WWC DCCCD you've all got a seat it's already got a fair amount of documentation for which we thank our doc team some pieces aren't quite fully functional the SQLite support only supports basic fetching and updating the live controllers aren't as live as we'd like them to be and the fetch properties don't fully work there isn't any localization and there's no optimisation but please try it out and if you find something submit bug reports we like bug reports they tell us you know what parts of the stack people are using what parts they don't really care about what problems they're having with things so things you think you should remember core data's model-driven gives you object graph management object graph persistency cocoa bindings and some additions to cocoa bindings it helps you solve difficult problems things like undo redo and scalability issues both of these are actually you know relatively hard as many of you know who've had to solve these problems before we do it for you we support a variety of persistent stores that you pick which particular storage mechanism you want we have support in Xcode and interface builder at the user interface level for allowing you to build applications using core data and you know you'll write a lot less code as Chris showed you in his demo a lot lot less code you don't even need classes you can just use ns-managed object before we go to the question and answer I want to point out this slide big slide report bugs griping on the list talking on the list that's all well and good but you know Apple engineering is bug driven submit bugs if you want us to fix things