Re: (simple?) CoreData question :-)
Re: (simple?) CoreData question :-)
- Subject: Re: (simple?) CoreData question :-)
- From: Melissa Turner <email@hidden>
- Date: Fri, 3 Mar 2006 13:35:10 -0800
The answer depends on the user visible semantics you want in the
second MOC, and the state of the objects in the second MOC.
There is no inter-context notification done automatically by
CoreData, so in all cases, the first MOC will post a
NSManagedObjectContextDidSave notification that your application
should register for and use as the trigger for whatever actions it
needs to take. This notification contains information about deleted
objects, but also about changed objects, which will also need to be
handled since these changes may be the result of the delete (most of
the ways this can happen involve transient relationships or fetched
properties, but it is possible). If you had this problem between
processes, OSX & Cocoa provide a number of other mechanisms you can
use to increase the scope of CoreData change notifications like
NSDistributedNotificationCenter and kqueues.
There are multiple axes you consider when deciding how you want to
handle your delete notification. The important ones are: what other
changes exist in the second MOC; whether or not the instance of the
object that was deleted has changes in the second MOC; and whether or
not changes in the second MOC can be undone. These are somewhat
orthogonal, and what actions you take to synchronize the contexts
depend on the semantics of your application.
1) The simplest case is when the object itself has not changed in the
second MOC and you don't have to worry about undo; in this case, you
can just delete the object. The next time this context saves, the
framework will notice that you're trying to re-delete something,
ignore the optimistic locking warning, and life will go on happily.
2) The next simplest is when you don't care about the contents of the
second MOC: you can simply reset it and refetch any data you need
after the reset. This will reset the undo stack as well, and the
deleted object is now gone. The only trick here is figuring out what
data to refetch - this can be done by collecting the oids before you
reset, and using those to reload once the reset has happened (you'll
need to exclude the deleted oids, and probably you want to do fetch
requests with IN predicates to unforseen weirdness and problems will
not being able to fulfill faults for deleted oids).
Things start getting complicated after this.
3) If the object has changed in the second MOC, but you don't care
about undo, your response depends on what it means for the semantics
of your application. If the object that was deleted in MOC1 has
changes in MOC2, should it be deleted from MOC2 as well? Or should it
be resurrected and the changes saved? What happens if the original
deletion triggered a cascade delete for objects that have not been
faulted into the second MOC? What if the object was deleted as part
of a cascade delete? 3a) The simplest answer here is to just discard
the changes by deleting the object.
3b) If the object is standalone, you can set the merge policy on the
context to NSMergePolicyOverwrite. This will cause the changes in the
second context to overwrite the delete in the database. Note that
this will cause ALL changes in MOC2 to overwrite any changes made in
MOC1.
These are the best solutions, and are least likely to leave your
object graph in some unsustainable state as a result of something you
missed. For the brave of heart (or the utterly insane) continue reading.
3c) If the object isn't standalone, and for some reason you want to
save those changes, the best you're likely to be able to do is to
resurrect the part of the graph that had been loaded into the second
MOC, which may or may not make sense in the context of your
application. This is again done by setting the merge policy to
NSMergePolicyOverwrite, but requires some up-front application
design, and some meddling with the objects in the 'deleted' object's
relationships. In order for the world to make some amount of sense
later, you need to automatically fault in any relationships that
might need to be resurrected when you fault in the object. Then, when
you get a delete notification, you'll need to make the context think
all the objects related to the 'deleted' object have changed, so that
they will be saved as well. This is going to bloat your application's
memory use, since you'll end up with possibly irrelevant data sitting
around as a precaution against something that may not happen, and if
you're not careful, you can end up with your database in a hybrid
state where it's neither what MOC1 tried to create, nor what MOC2
would expect (you missed a relationship somewhere and you now have
partial relationships, or orphaned nodes). ****This is probably a bad
idea.****
4) The second worst of all worlds is when you have changes to other
objects you can't blow away in the second MOC, the object itself has
changes that you are willing to discard, and you care about undo. You
can't reset the context, because that loses the changes. If you
delete the object, the delete will get pushed onto the undo stack and
will be undoable, so the user could undo, resave, and run into the
semantic problems I talk about in part 3, only worse because you
haven't planned for them. The only real way to solve this is to keep
track - separately, in your application code - of the objects which
are changed as a result of the delete. You then need to track user
undo events, and when the user undoes past a delete, you can then
'rerun' the deletion. ****This is going to get messy and inefficient
very quickly if there are a significant number of changes being
propagated.***
5) Worst case is you have changes to other objects you can't/won't
discard, the object has changes you want to keep, and you care about
undo. There's probably a way to do it, it will be insanely ugly and
complicated and I'm not going to provide any rope here.
If you find yourself in cases 3c-5, you should probably just redesign
your application's model to bring you into 1-3b.
+Melissa
On Mar 2, 2006, at 10:19, Mr. Guillaume Christian Rager wrote:
Hey
I have core data application that uses SQLite store.
The persistent store coordinator is shared between 2 MOCs.
When the user deletes an object in MOC moc1, the deletion is seen
by NSArrayControllers and the tableview are refreshed.
How can i inform the second MOC that the object with the same
objectID (i'll use objectWithObjectID:) has been removed? is it up
to me to inform the second MOC app that an object has been deleted
in the first MOC? should i remove this object again (using
objectWithObjectID:) in the second MOC ?
thanks
Guillaume
-----------
GUMITECH - France
http://www.gumitech.com
"Chaud cocoa, chaud chocolat !"
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden