iPh*_*ire 4 iphone core-data objective-c
我有一个基于CoreDataBooks示例的应用程序,它使用一个addingManagedObjectContext来添加Ingredient到a Cocktail以撤消整个添加.在CocktailsDetailViewController随后调用BrandPickerViewController为给定的成分(可选)设置一个品牌名称.Cocktail,Ingredient并且Brand都是NSManagedObjects.Cocktail需要至少设置一个Ingredient(baseLiquor),所以我在创建时创建它Cocktail.
如果我Cocktail在CocktailsAddViewController : CocktailsDetailViewController没有设置的情况下添加in (在保存时合并到Cocktail托管对象上下文中)baseLiquor.brand,那么它可以Brand在稍后从一个选择器(也存储在Cocktails托管上下文中)设置CocktailsDetailViewController.
但是,如果我尝试设置baseLiquor.brand在CocktailsAddViewController,我得到:
由于未捕获的异常'NSInvalidArgumentException'而终止应用程序,原因是:'非法尝试在不同上下文中的对象之间建立关系'品牌'
从这个问题我明白问题是Brand存储在应用程序中managedObjectContext并且新添加Ingredient并Cocktail存储在其中addingManagedObjectContext,而传递它ObjectID会避免崩溃.
我不明白的是如何实现的选择器一般让所有的成份(的baseLiquor,mixer,garnish等)可附加期间设置,以及一个接一个从CocktailsDetailViewController后Cocktail已创建.换句话说,在CoreDataBooks示例之后,在添加和编辑的情况下,何时何地将从父MOC ObjectID变为NSManagedObject?-IPD
更新 - 这是添加方法:
- (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];
}
Run Code Online (Sandbox Code Playgroud)
这里是Brand选择器中崩溃的站点(这NSFetchedResultsController是由app delegate的托管对象上下文支持的:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
if ([delegate respondsToSelector:@selector(pickerViewController:didFinishWithBrand:forKeyPath:)])
{
[delegate pickerViewController:self
didFinishWithBrand:(Brand *)[fetchedResultsController objectAtIndexPath:indexPath]
forKeyPath:keyPath]; // 'keyPath' is @"baseLiquor.brand" in the crash
}
}
Run Code Online (Sandbox Code Playgroud)
最后代表实施:
- (void)pickerViewController:(IngredientsPickerViewController *)pickerViewController
didFinishWithBrand:(Brand *)baseEntity
forKeyPath:(NSString *)keyPath
{
// set entity
[cocktail setValue:ingredient forKeyPath:keyPath];
// Save the changes.
NSError *error;
if (![cocktail.managedObjectContext save:&error]) {
// Update to handle the error appropriately.
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
exit(-1); // Fail
}
// dismiss picker
[self.navigationController popViewControllerAnimated:YES]
}
Run Code Online (Sandbox Code Playgroud)
更
我根据Marcus的建议制作了progess - 我将其映射addingManagedObjectContexts到父的managedObjectContext并将所有内容包装起来begin/endUndoGrouping以处理取消与保存.
但是,要创建的对象在a中NSFetchedResultsController,因此当用户点击"+"按钮添加时Cocktail,(可能要撤消的)实体会短暂出现在表视图中,因为模式添加视图控制器已呈现.MDN示例是基于Mac的,因此它不会触及此UI行为.我该怎么做才能避免这种情况?
听起来你正在创建两个不同的核心数据堆栈(NSManagedObjectContext,NSManagedObjectModel,和NSPersistentStoreCoordinator).你想从这个例子中做的只是创建NSManagedObjectContext指向相同的两个实例NSPersistentStoreCoordinator.这将解决这个问题.
把它想象NSManagedObjectContext成一个便笺簿.您可以拥有任意数量的内容,如果在保存之前丢弃它,其中包含的数据就会消失.但他们都保存到同一个地方.
不幸的是,CoreDataBooks是一个非常可怕的例子.但是,对于您的问题,我建议删除附加上下文的创建,并查看是否发生错误.基于您发布的代码,我假设您直接从Apple的示例中复制的代码,双重上下文,虽然几乎没用,应该可以正常工作.所以我怀疑还有别的东西在起作用.
尝试使用单个上下文,看看问题是否仍然存在.你可能有一些其他有趣但微妙的错误,它会给你这个错误; 也许是某个地方的过度释放或沿着那些方向的东西.但第一步是删除双重上下文,看看会发生什么.
如果即使使用单个MOC也会崩溃,那么您的问题与上下文无关.单个MOC的错误是什么?当我们解决这个问题时,我们将解决您的整个问题.
至于更好的解决方案,请NSUndoManager改用.这就是它的设计目标.Apple 真的不应该在他们的例子中推荐多个MOC.
我最近在这里回答了一个关于使用NSUndoManager核心数据的问题,但你也可以在MDN上看一些我的文章作为例子.