views:

24

answers:

1

I need some advice how to go about this:

1) I retrieve an XML from a web server.

2) I want to store all the entities (i.e. Friends) from that XML locally on the device, using Core Data.

3) So I parse the XML and make an Managed Object for every Friend in that XML

4) But I want to make sure that I don't add one Friend multiple times into the DB. How could I achieve that?

-------------- my strategy thoughts on this ----------------

A) While parsing the XML, I create an Managed Object of the Friend entity as soon as there is a Friend element started. At that point I don't know which friend it will be, until the NSXMLParser stepped through all the upcoming attributes like firstName, id, etc.; After the End-tag for the Friend element, I have that friend in my Managed Object Context. Then I make an NSFetchRequest to see if that friend is stored already. Problem is, that the new friend is already part of the context, so probably Core Data will return always a match!?

B) I need two different Managed Object Contexts so that the parsed Friends first go into MOC_A, and then I query MOC_B (the actual local store) without that the new parsed friends disturbe my query to the local store. So I can find out if the friend already existed.

C) While parsing a friend from the XML I just create a new Managed Object instance WITHOUT adding it to an Managed Object Context (possible ?!). Later, when the friend is pares completely, I check against Core Data if it is stored. If not, I add it. Otherwise I throw the object away.

D) I need another strategy.

+3  A: 

You should use a new indexed attribute in your Core Data entity to store the unique ID from the XML. Before adding an object, you will have to manually check if an object with that ID already exists.

UPDATE
The key is to not add a managed object to the context until you have determined that it is new.
This is pretty straightforward given the unique ID, but it sounds like you can't parse for the unique ID first. In that case you should use a temporary mutable dictionary (NSMutableDictionary) to store the data as it's parsed.
If you determine that the friend is new, you can create it and copy the data over from the dictionary. If the friend is not new, you can discard the dictionary.

gerry3
Well, you haven't answered it really: The problem is that the managed object is created as soon as the NSXMLParser matches the beginning of a new object, and thus that MO goes right into the Managed Object Context. And then, the question is still open: If it lives already in the context, how can I: a) safely query core data if it exists (it does, in the context! So I always get a match, don't I?), b) safely throw this object away if one if its kind is >stored< already.
dontWatchMyProfile
I have updated my answer given the new information. Ideally, you would be able to parse the unique ID first and perform the check right away. If this isn't possible, I suggest using a temporary dictionary. Let me know if you have any questions about this approach.
gerry3
Thanks for the update, mate. Now that makes sense :). Okay, so lets say I can't add that into the MOC as soon as the parser steps into it. Couldn't I just instantiate the custom class for that Managed Object, lets say 'Friends', and populate the properties as needed? A problem I see is that the properties are "dynamic", and I believe Core Data creates these. But in that case Core Data wouldn't do anything in the first place, so I can't use that class for temporary objects unless I modify it deeply -> could I modify that without interrupting Core Data? Could I add instance variables?
dontWatchMyProfile
Addition: What I try to say is: Can I use the custom class for my 'Friend' entity rather than duplicating data structure with a Dictionary? It would make some sense to me to use the Friend class for temporary data storage until parsing it finished, and I'm able to determine if it exists in Core Data already or not. And if it doesn't, then I create a new MOC by copying over all the values from the temp object, otherwise I just throw the temp object away. Of course your dictionary approach is fine too if the other way is not working well. good idea.
dontWatchMyProfile
Unfortunately, the only way to instantiate a managed object subclass is by inserting it into a context. So the dictionary is the best approach that I know of. You could also create a subclass of NSObject with ivars and the same properties as your Friend class and use that for the temporary object(s) rather than a dictionary.
gerry3
Thanks. Because this is something completely different, I opened a new question for that problem: http://stackoverflow.com/questions/2251158/can-i-create-manually-an-instance-of-an-core-data-entity-class-for-temporary-usag
dontWatchMyProfile