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