Question

I am trying to parse a XML document and store its data in a Core Data store using an background queue. I am using the new nested UIManagedObjectContext concept introduced in iOS 5.

I have added a new category to my NSManagedObject company, which handles the parsing of company specific data:

- (void)parseAttributesFrom:(NSString*)xmlStr 
             inManagedObjectContext:(NSManagedObjectContext*)managedObjectContext 
  {
  NSManagedObjectContext * context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];

  context.parentContext = self.managedObjectContext;
  [context performBlock:^{

                IBCompany *company = self;
                [company setValue:[[[document.root childNamed:@"CoIDs"] childWithAttribute:@"Type" value:@"CompanyName"] value] forKey:@"companyName"];
            ...

This is how I call this method: [company parseAttributesFrom:xmlStr inManagedObjectContext:self.managedDocument.managedObjectContext]; Please note that my issue is unchanged, even if I pass the managed object context as a parameter to the method.

When I run the code, it crashes where I set the annualPeriod to the company with the error message NSInvalidArgumentException: 'Illegal attempt to establish a relationship 'company' between objects in different contexts (source = <IBEstPeriod: ...:

IBEstPeriod *annualPeriod = [NSEntityDescription insertNewObjectForEntityForName:@"IBEstPeriod" inManagedObjectContext:context];
[annualPeriod setCompany:company];

I am struggling to understand why the error should be related to different contexts when the code runs in the same background ideas. I would appreciate any help!!

Was it helpful?

Solution

I think, that reason is that IBCompany *company = self; is in the context you pass, and then you set the new connection in another context.

That's the reason.

OTHER TIPS

You may not do this:

context.parentContext = self.managedObjectContext;

if you are using UIManagedDocument as in here:

[company parseAttributesFrom:xmlStr inManagedObjectContext:self.managedDocument.managedObjectContext];

That is because UIManagedDocument already uses nested contexts and self.managedDocument.managedObjectContext has its parent context set. Now you are swapping it out and by doing that you break things.

Here's a quote from UIManagedDocument Class Reference.

To support asynchronous data writing, Core Data actually uses a pair of nested managed object contexts. The parent context is created on a private thread, the child context is created on the main thread. You get the child context from the managedObjectContext property.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top