Saving Single CoreData Entity (Not the Whole Context) While Keeping NSFetchedResultController Functionality
J

2

9

Phew, sorry for the long title.

I have a single Managed Object Context where I am storing songs derived from two different locations. I get some of the songs from the persistent storage on the phone (using Core Data), and I pull some of the songs from an online database. Both of the songs are of the same MananagedObject subclass. I would like both of these songs to be in a single context because I would like them both to show up on a table view connected with an NSFetchedResultsController.

The problem occurs when I would like to save one of the songs. I don't want to save all of the songs that I pulled from the online database to the phone. I just want to save the single song, so a simple [moc save] doesn't work. The other issue is that after I save the single song, I still want the songs pulled from online to be in the context (but again, not saved). I believe I have a couple of different options:

1) Is it possible to have an NSFetchedResults controller connected to multiple contexts?

2) I could move all of the songs pulled from the online database into a separate temporary context, save in the original context, and then move all of the songs back. (see: How do I copy or move an NSManagedObject from one context to another?)

3) Remember all of the key-value pairs for the online songs, delete the online songs from the context, save the original context, insert all of the online songs back into the original context based off of the saved key-value pairs.

4) I am a huge n00b and am missing something easier.

Thanks!

Joshi answered 8/8, 2012 at 0:25 Comment(1)
What do you actually want to save? The location of the song or the actual song data (file)?Shavonneshaw
D
8

I think the easiest thing to do would be to have a second NSPersistentStore attached to your persistent store coordinator. You can have that store be an in-memory store, and store all your "online" results in that (temporary) store. You can specify which store a newly-inserted object should be saved in with assignObject:toPersistentStore:. Once you've done this, you can save freely, since the "save" will only happen to memory for your online songs.

Then, when you want to move a song from the online set to the permanent set, just delete it and re-insert it, assigning the new object to your permanent persistent store with the same method.

This will let you use a single NSManagedObjectContext attached to your NSPersistentStoreCoordinator, which will see objects from both of the NSPersistentStores.

Disembowel answered 8/8, 2012 at 0:56 Comment(2)
Apple promotes using multiple persistent stores for similar scenarios (like canned starter data that comes with the app). I'd say it's a good idea whenever you have entities whose persistent storage plans differ.Boling
Careful if you're maintaining relationships between entities which are using different persistent stores. According to our friends at Apple: "You must be careful not to create relationships from instances in one persistent store to instances in another persistent store, as this is not supported by Core Data. If you need to create a relationship between entities in different stores, you typically use fetched properties" developer.apple.com/library/mac/documentation/Cocoa/Conceptual/…Vesper
E
5

Jesse's solution will work just fine.

However, as another option, you can simply use a nested context, just like you would for a detailed inspector.

That context can hold all your "temporary" items, but since it is a child of your "saving" context, all fetches will work just fine.

NSManagedContext *tempContext = [[NSManagedContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
tempContext.parentContext = mainManagedObjectContext;

ALl your saves will be inserted into mainManagedObjectContext, and saved with save:. All your temporary items will go into tempContext.

Attach your fetched results controller to the tempContext as well.

When you are ready to get rid of the temporary items, just set the tempContext to nil.

Emelyemelyne answered 8/8, 2012 at 2:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.