views:

280

answers:

3

In my project I have some objects that I show from a server, lets call them Foo's. When I get my Foo feed, I parse them into a NSMutableDictionary subclass called RemoteFoo, and pass these RemoteFoo objects all around the app to display data.

If the user ends up wanting to download a RemoteFoo, I then create a core-data NSManagedObject entity called Foo, and instantiate it using the values from the RemoteFoo. All this works.

The problem I have is that If I want a method to run on a RemoteFoo and a Foo, I have to duplicate it in both RemoteFoo.m and Foo.m. Also, my app if full of duplicate init's like:

- (id)initWithFoo:(Foo *)foo;
- (id)initWithRemoteFoo:(RemoteFoo *)foo;

How can I avoid all of this code-duplication while still separating the temporary remote RemoteFoo from the core-data Foo entities that represent the Foo the user has saved locally?

+2  A: 

You could just save all RemoteFoo's as Foo's and work with those. If you need different behavior, you could have an attribute on Foo indicating if it's remote or not.

Jaanus
RemoteFoos change constantly though, and are requested in various lists from the server in multiple ways, through multiple points in the app. If I save them all, I would have to constantly update each Foo record I have of them as the details for each RemoteFoo may change. I think this would add much overhead to my app's performance. Not to mention there are thousands of RemoteFoo's, but only dozens of Foo's that the user will download.
coneybeare
This definitely seems like the easiest way… do you think there would be a performance hit using it like I describe in the above comment?
coneybeare
Core Data has been heavily tuned for performance. You can't yourself be more efficient with your homebrew solution than you would be using CoreData.
Jaanus
+1  A: 

Change your Core Data model as follow. Use one Foo instance and add a boolean attribute isRemote (or something similar) that you set by default to NO. When you download your remote objects, instantiate those as Foo managed objects and set their isRemote attribute to yes.

This way, you only need to deal with one instance in your app, while retaining the ability to clearly differentiate between local and remote Foo objects. If your app allows this you may even declare the isRemote attribute as transient, so that it will never be stored on disk, just in memory. If you do no care to persist this information, then this may be the best way to go.

unforgiven
This answer is similar to Jaanus, but I did not know about the transient option. That sounds appealing because the RemoteFoos generally wont change in a single session, so saving to memory sound ok. I will research more on this
coneybeare
hmm, i misread. I thought the whole Foo could be tranient, but just colums can be.
coneybeare
+1  A: 

Have you thought of using something like a class cluster -

http://seanmurph.com/weblog/make-your-own-abstract-factory-class-cluster-in-objective-c/

    --------- Foo --------          NSManagedObject
    |                    |                 |
RemoteFoo             LocalFoo ------ CoreDataFoo 
James Raybould
Hi, This is definitely the way I wish to go, but core data entities have to be a subclass of NSMangedObject
coneybeare
I know is a little messy but wouldn't it be possible to have a mediator between the core data entities and a class in the Foo class cluster? I'll add a little diagram to my postI feel like I should add the disclaimer that I'm very sleepy and very hungry right now - so my answers maybe a little crazy!
James Raybould
How would interaction between LocalFoo and CoreDataFoo work exactly? Can you give some short example of how MediatorFoo would work and its hookups?
coneybeare
Well LocalFoo could just forward messages on from Foo to CoreDataFoo and pass the data back from CoreDataFoo to Foo.
James Raybould