0

This is a follow up to an earlier question: Core Data: change delete rule programmatically.

I'd like to rephrase my question, and will do that here.

Briefly, my app allows updating entries from a 3rd party database, but I'd like to keep user annotations. So my workflow is:

  1. iterate over all entities
  2. download external xml and parse it into a new entity
  3. if user annotations, change their relationship from old entity to new entity
  4. delete old entity

During the import, the old entity is in the main context, the new entity is in a temporary import context. Number 3 gives me problems, if I just change the relationship, then they don't show if I update my UI. If I use the objectID to get the annotation and then change the relationship as follows:

    NSManagedObjectID *objectId = oldAnnotation.objectID;
    Annotation *newAnnotation = [importContext objectWithID: objectId];
    [newEntry addAnnotationObject: newAnnotation];

It's still not working - it's not showing up.

EDIT: if I change the context in the second line to newEntry.managedObjectContext, I get an Illegal attempt to establish a relationship 'foo' between objects in different contexts error.

What am I missing?

UPDATE: After some late-night hair-pulling debugging, I found that I when I was fetching the newEntry, I was actually fetching the oldEntry, therefore none of the changes would show up. The answer below by @Mundi pointed me in the right direction.

Copying the old annotations worked using my code above, followed by copying the attributes. For some user input with relationships in itself, I had to do a "Deep Copy", which I found here: How can I duplicate, or copy a Core Data Managed Object?.

Community
  • 1
  • 1
koen
  • 5,383
  • 7
  • 50
  • 89

1 Answers1

1

I think creating a new entity and deleting the old one is a problematic strategy. You should try to properly update the existing entities and only create new ones if they do not yet exist.

Whenever I need an object from a different context, I fetch it. That being said, your object id code should work. However, there could be all sorts of other glitches, that you should check:

  • Did you save the importContext?
  • Did you save its parent context, presumably the main context?
  • Was the modified object graph saved to the persistent store?
  • Are you checking the results after you have saved?
Mundi
  • 79,884
  • 17
  • 117
  • 140
  • I have considered updating the entries, but they are highly branched with many relationships, each of which could have a small update. So instead of iterating through them all, and find the corresponding info in the xml file that I am parsing, I decided to do a brute force replacement, and copy over the user entered annotations. Unless it is somehow possible to create the new entry and merge it with the old one, overriding whatever is changed. But I guess that requires another iteration over all the relationships and copying the changes from the old to new entry. – koen Apr 10 '16 at 21:23
  • As stated, I believe your brute force approach to be bad design. Updating instead of creating should not introduce more complexity or require more code. To stay consistent, you could also *copy* the user annotations. – Mundi Apr 10 '16 at 21:26
  • Point well taken - I am going to look into updating the entries. And regarding copying the annotations, do you mean creating a new one and copying the attributes? – koen Apr 10 '16 at 21:34
  • Yes, copying the attributes. But this would only be a recommendation if you stick with your brute force re-creation approach. – Mundi Apr 11 '16 at 06:17
  • I found this link: http://simianzombie.com/?p=2379 - it may help with what I am trying to do. – koen Apr 11 '16 at 12:16
  • Actually, I think the question really should be: "How do I merge two `NSManagedObjects` in different contexts, keeping the most up-to-date information" – koen Apr 12 '16 at 12:18