NSInvalidArgumentException: Illegal attempt to establish a relationship between objects in different
Posted
by iPhoneDollaraire
on Stack Overflow
See other posts from Stack Overflow
or by iPhoneDollaraire
Published on 2010-03-10T12:00:43Z
Indexed on
2010/03/12
1:47 UTC
Read the original article
Hit count: 548
I have an app based on the CoreDataBooks example that uses an addingManagedObjectContext
to add an Ingredient
to a Cocktail
in order to undo the entire add. The CocktailsDetailViewController
in turn calls a BrandPickerViewController
to (optionally) set a brand name for a given ingredient. Cocktail
, Ingredient
and Brand
are all NSManagedObjects
. Cocktail
requires at least one Ingredient
(baseLiquor
) to be set, so I create it when the Cocktail
is created.
If I add the Cocktail
in CocktailsAddViewController : CocktailsDetailViewController
(merging into the Cocktail managed object context on save) without setting baseLiquor.brand
, then it works to set the Brand
from a picker (also stored in the Cocktails managed context) later from the CocktailsDetailViewController
.
However, if I try to set baseLiquor.brand
in CocktailsAddViewController
, I get:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Illegal attempt to establish a relationship 'brand' between objects in different contexts'
From this question I understand that the issue is that Brand
is stored in the app's managedObjectContext
and the newly added Ingredient
and Cocktail
are stored in addingManagedObjectContext
, and that passing the ObjectID
instead would avoid the crash.
What I don't get is how to implement the picker generically so that all of the Ingredients (baseLiquor
, mixer
, garnish
, etc.) can be set during the add, as well as one-by-one from the CocktailsDetailViewController
after the Cocktail
has been created. In other words, following the CoreDataBooks example, where and when would the ObjectID
be turned into the NSManagedObject
from the parent MOC in both add and edit cases? -IPD
UPDATE - Here's the code:
- (IBAction)addCocktail:(id)sender {
CocktailsAddViewController *addViewController = [[CocktailsAddViewController alloc] init];
addViewController.title = @"Add Cocktail";
addViewController.delegate = self;
// Create a new managed object context for the new book -- set its persistent store coordinator to the same as that from the fetched results controller's context.
NSManagedObjectContext *addingContext = [[NSManagedObjectContext alloc] init];
self.addingManagedObjectContext = addingContext;
[addingContext release];
[addingManagedObjectContext setPersistentStoreCoordinator:[[fetchedResultsController managedObjectContext] persistentStoreCoordinator]];
Cocktail *newCocktail = (Cocktail *)[NSEntityDescription insertNewObjectForEntityForName:@"Cocktail" inManagedObjectContext:self.addingManagedObjectContext];
newCocktail.baseLiquor = (Ingredient *)[NSEntityDescription insertNewObjectForEntityForName:@"Ingredient" inManagedObjectContext:self.addingManagedObjectContext];
newCocktail.mixer = (Ingredient *)[NSEntityDescription insertNewObjectForEntityForName:@"Ingredient" inManagedObjectContext:self.addingManagedObjectContext];
newCocktail.volume = [NSNumber numberWithInt:0];
addViewController.cocktail = newCocktail;
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:addViewController];
[self.navigationController presentModalViewController:navController animated:YES];
[addViewController release];
[navController release];
}
© Stack Overflow or respective owner