我有一个基于coredatabooks示例的应用程序,它使用addingManagedObjectContextIngredient添加到Cocktail以撤消整个添加。CocktailsDetailViewController依次调用BrandPickerViewController来(可选)为给定的成分设置品牌名称。CocktailIngredientBrand都是NSManagedObjectsCocktail需要至少设置一个IngredientbaseLiquor),因此我在创建Cocktail时创建它。
如果我在Cocktail中添加CocktailsAddViewController : CocktailsDetailViewController(保存时合并到cocktail managed object context)而不设置baseLiquor.brand,则可以在稍后从Brand中从选择器(也存储在cocktail managed context中)设置CocktailsDetailViewController
但是,如果我尝试在baseLiquor.brand中设置CocktailsAddViewController,则会得到:
由于意外异常而终止应用程序
“nsInvalidargumentException”,原因:
'非法建立
对象之间的关系“品牌”
在不同的背景下
this question我了解到,问题是Brand存储在应用程序的managedObjectContext中,新添加的IngredientCocktail存储在addingManagedObjectContext中,而通过ObjectID将避免崩溃。
我不知道的是如何实现选择器,以便在添加过程中设置所有成分(baseLiquormixergarnishCocktailsDetailViewController,等等),以及在创建Cocktail之后从ObjectID中逐个设置。换句话说,遵循coredatabooks示例,在添加和编辑情况下,何时何地将NSManagedObject从父moc转换为Brand?-IPD公司
更新-下面是add方法:

- (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];

}

这里是NSFetchedResultsController选取器中崩溃的站点(这个addingManagedObjectContexts由app委托的托管对象上下文支持:
- (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
    }
}

最后是委托实现:
- (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]
}

甚至更多
我正在根据马库斯的建议进行编程——我将begin/endUndoGrouping映射到父managedobjectcontext,并将所有内容打包到NSFetchedResultsController中以处理取消与保存。
但是,要创建的对象位于Cocktail中,因此当用户点击“+”按钮添加时,表视图中会短暂出现(可能要撤消的)实体,显示模式添加视图控制器。mdn示例是基于mac的,因此它不涉及这个ui行为。我能做些什么来避免这个?

最佳答案

听起来您正在创建两个不同的核心数据堆栈(NSManagedObjectContextNSManagedObjectModelNSPersistentStoreCoordinator)。从示例中要做的是创建两个指向相同的NSManagedObjectContextNSPersistentStoreCoordinator实例。这将解决这个问题。
NSManagedObjectContext当作一个便笺簿。您可以拥有任意数量的数据,如果在保存之前将其丢弃,则其中包含的数据将不复存在。但它们都保存在同一个地方。
更新
不幸的是,coredatabooks是一个非常糟糕的例子。但是,对于您的问题,我建议删除附加上下文的创建,并查看是否发生错误。根据你发布的代码,我假设你直接从苹果的例子中复制的代码,双上下文,虽然实际上没用,但应该可以正常工作。所以我怀疑还有别的事情在起作用。
尝试使用单个上下文并查看问题是否仍然存在。你可能有其他一些有趣但微妙的错误,这是给你这个错误,也许是某个地方或沿这些线的东西的过度删除。但第一步是移除双重上下文,看看会发生什么。
更新2
如果它崩溃了,即使只有一个moc,那么你的问题与上下文无关。单台MOC的错误是什么?当我们解决了这个问题,我们就会解决你的整个问题。
对于更好的解决方案,请使用NSUndoManager。这就是它的设计目的。苹果真的不应该在他们的例子中推荐多个moc。
我最近在这里回答了一个关于对核心数据使用NSUndoManager的问题,但是您也可以以我关于mdn的一些文章为例。

10-07 20:40