How to set a relationship from one NSManageObject to another in a different NSManagedObjectContext
Because my app is multi-threaded I use two NSManagedObjectContexts. The main context, that runs in the main thread and another context that only runs in a separate thread.
I have created a small test app. It has two Core Data Entities. Parent and Child. Parent has a one-to-many relationship to Child. Child has a 1-1 relationship to Parent.
In one test method (that runs in a separate thread) I get a Parent instance, that has been created during a run time before. So it's in the main context. I get this parent with this line of code:
Parent *tmpParent = [[parentController selectedObjects] objectAtIndex:0];
Then I create some children in the thread-context (managedObjectContextInBackground), set their parent to the tmpParent, give them a name and save the thread-context:
Child *child1 = (Child *)[NSEntityDescription insertNewObjectForEntityForName:@"Child" inManagedObjectContext:managedObjectContextInBackground]; [child1 setName:@"Homer"]; [child1 setParent:tmpParent]; Child *child2 = (Child *)[NSEntityDescription insertNewObjectForEntityForName:@"Child" inManagedObjectContext:managedObjectContextInBackground]; [child2 setName:@"Wilma"]; [child2 setParent:tmpParent]; [self saveManagedObjectContextInBackground];
If I execute that method the application crashes and says: Illegal attempt to establish a relationship 'parent' between objects in different contexts
That's why I added this line below the tmpParent declaration:
But, the application crashes again saying: An NSManagedObject may only be in (or observed by) a single NSManagedObjectContext
I looked through the documentation, but I couldn't find a way to solve this problem.
Question: How can I set the relationship of Child to Parent, when Parent is in a different NSManagedObjectContext, than Child ??
Your object can be loaded from another context, thus, when you create a new NSManagedObject in your other thread, nothing stops you from fetching an existing NSManagedObject which may or may not be being used in the main thread, and use that reference in order to set up your relationship.
When you exit the thread and merge the contexts, this change will get updated for the object that was until this point happily existing in memory on the main thread.