Using NSManagedObject subclasses to transport persistent and non persistent data
Asked Answered
D

3

6

I'm having some thoughts on how to use some core data's NSManagedObject subclasses to handle persistent data and non persistent data.

Let's say you have a recipe app displaying a list of your own recipes from CoreData and in this same app you can search for other users recipes as well. These other users recipes are of course from an API and we don't want to save them into core data. But what we want instead is our recipe detail View Controller to act the same either it is given a persistent recipe or a non persistent recipe. I naturally think that we should then use the same object wrapper around our data and let our View Controller to be blind on the origin of the data.

The problem is that NSManagedObject subclasses cannot be initialized manually and have to be inserted into the context. That's not good for our other users recipes. On the other hand for our own recipes we need these object to be inserted into the context.

I have a couple of solutions in mind but I'd really like to read what you guys think of this issue.

Would you say that this is some implementation issue and should be solved by wrapping both data objects into one single object ? For example by overriding all getters and setters to handle both coredata objects and NSDictionary objects ?

Or is it an architecture issue, and you would solve it by for example nesting NSManagedContext, or using multiple persistent stores (one in memory and the other one Sqlite) ?

Dempstor answered 11/4, 2013 at 16:41 Comment(0)
U
7

Actually you can create NSManagedObject instances without inserting them into a context. Just pass nil as the managed object context argument. Do something like:

NSEntityDescription *myRecipeEntity = [NSEntityDescription entityForName:@"MyRecipeEntity" inManagedObjectContext:[self managedObjectContext]];
MyRecipeClass *recipe = [[MyRecipeClass alloc] initWithEntity:myRecipeEntity insertIntoManagedObjectContext:nil]];

Now you have a recipe instance that's not in any context.

If you later want to add it to a context:

[[self managedObjectContext] insertObject:recipe];

If you don't want to insert it, just throw it away.

Uptotheminute answered 11/4, 2013 at 17:18 Comment(7)
You cannot have relationships between objects that are not inserted into context as far as I know.Tabloid
Sure. But that doesn't always matter.Uptotheminute
Thx this might be a solution... I'll try that and let you guys knowDempstor
Hey This really seems to work, and you are right in my case not having relationships for temporary objects is not really what matters. By the way initWithEntity:insertIntoManagedObjectContext: seems to be an instance method not a class method and can be used as any other init method. Thx a lot I'm accepting this answer right now ;)Dempstor
I wrote a demo for this on OSX and had issues, where attributes would not get saved (see github.com/seltzered/CoreDataMagicalRecordTempObjectsDemo). From my results it seems that using a child context is a safer approach, as suggested in a similar question - https://mcmap.net/q/235973/-how-to-deal-with-temporary-nsmanagedobject-instancesTumble
Is the failing version contained in that project somewhere? There's no reason why using Core Data with the approach described above would not save attributes. Without seeing code it's impossible to say why it didn't work for you, but it's possible that this is a side effect of adding Magical Record.Uptotheminute
Yes, my approach of using an object with a nil context then inserting it into a default context is the highlighted section: github.com/seltzered/CoreDataMagicalRecordTempObjectsDemo/blob/… , apologies for just hastily throwing all this in the applicationDidFinishLaunching.Tumble
B
1

I would likely just use a separate context that you never save, that seems to be the simplest route.

Beating answered 11/4, 2013 at 17:2 Comment(0)
T
0

Model configurations - in-memory store and sqlite backed store.

I would seriously consider using model configurations and two persistent store types: in-memory and sqlite backed.

But it also means that you would have to create separate entities for downloadable data which kind of nullifies the idea that you can have some of the recipes persistent and some temporary while they are both recipes. Also, you cannot have relationships between entities in different persistent stores. You'll give up the benefit of inverse relationships and have to imitate this with fetched properties for example.

All in all, it's a viable choice with some disadvantages.

Isolated Managed Object Context

The biggest advantage of using separate managed object contexts is you can use the same recipe entity for both persistent and temporary data. You'll have to avoid saving the temporary context and will have to bring in all the changes from the persistent store or merge from other context that has the data you do save.

The challenge with this alternative is that you have to build most of your UI on top of this isolated context for reading, but all permanent changes you make need to be saved to your main context and propagated back through merging into the isolated context. This might introduce some tricky situations, but it's doable I think.

Tabloid answered 11/4, 2013 at 20:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.