views:

556

answers:

1

I'm converting an app from SQLitePersistentObjects to CoreData.

In the app, have a class that I generate many* instances of from an XML file retrieved from my server. The UI can trigger actions that will require me to save some* of those objects until the next invocation of the app.

Other than having a single NSManagedObjectContext for each of these objects (shared only with their subservient objects which can include blobs). I can't see a way how I can have fine grained control (i.e. at the object level) over which objects are persisted. If I try and have a single context for all newly created objects, I get an exception when I try to move one of my objects to a new context so I can persist it on ots own. I'm guessing this is because the objects it owns are left in the 'old' context.

The other option I see is to have a single context, persist all my objects and then delete the ones I don't need later - this feels like it's going to be hitting the database too much but maybe CoreData does magic.

So:

  1. Am I missing something basic about the way my CoreData app should be architected?
  2. Is having a context per object a good design pattern?
  3. Is there a better way to move objects between contexts to avoid 2?

* where "many" means "tens, maybe hundreds, not thousands" and "some" is at least one order of magnitude less than "many"

Also cross posted to the Apple forums.

+3  A: 

Core Data is really not an object persistence framework. It is an object graph management framework that just happens to be able to persist that graph to disk (see this previous SO answer for more info). So trying to use Core Data to persist just some of the objects in an object graph is going to be working against the grain. Core Data would much rather manage the entire graph of all objects that you're going to create. So, the options are not perfect, but I see several (including some you mentioned):

  1. You could create all the objects in the Core Data context, then delete the ones you don't want to save. Until you save the context, everything is in-memory so there won't be any "going back to the database" as you suggest. Even after saving to disk, Core Data is very good at caching instances in the contexts' row cache and there is surprisingly little overhead to just letting it do its thing and not worrying about what's on disk and what's in memory.
  2. If you can create all the objects first, then do all the processing in-memory before deciding which objects to save, you can create a single NSManagedObjectContext with a persistent store coordinator having only an in-memory persistent store. When you decide which objects to save, you can then add a persistent (XML/binary/SQLite) store to the persistent store coordinator, assign the objects you want to save to that store (using the context's (void)assignObject:(id)object toPersistentStore:(NSPersistentStore *)store) and then save the context.
  3. You could create all the objects outside of Core Data, then copy the objects to-be-saved into a Core Data context.
  4. You can create all the objects in a single in-memory context and write your own methods to copy those objects' properties and relationships to a new context to save just the instances you want. Unless the entities in your model have many relationships, this isn't that hard (see this page for tips on migrating objects from one store to an other using a multi-pass approach; it describes the technique in the context of versioning managed object models and is no longer needed in 10.5 for that purpose, but the technique would apply to your use case as well).

Personally, I would go with option 1 -- let Core Data do its thing, including managing deletions from your object graph.

Barry Wark
Thanks Barry I'd come to that conclusion myself after a few frustrating hours of research but it's very useful to have someone who actually knows what they're talking about confirm it.
Roger Nolan
No worries. We're all standing on the shoulders of giants. Good luck.
Barry Wark
I can confirm that 1. works well. I've implemented a complex app with about 25 different entity types that represent interrelated objects passed to me from a server. If the server objects have a type hierarchy, then mimic that with subentities in Core Data.
Steve Weller