Core data 核心数据-关系意外变为零

Core data 核心数据-关系意外变为零,core-data,nsmanagedobjectcontext,Core Data,Nsmanagedobjectcontext,我正在与核心数据中的一些奇怪行为作斗争。我有一个相当标准的设置,使用CoreDataBook示例:我有一个RootView,它使用NSFetchedResultsController来显示项目列表。项具有一些属性以及与其他实体的关系。我有一个DetailView,我用它来创建一个新的项目,以及编辑一个现有的项目,我以模态的方式呈现。在DetailView:viewDidLoad中,我创建了一个新的managedObjectContext,希望在其中进行所有更改。。。如果用户按Save,我将保存此

我正在与核心数据中的一些奇怪行为作斗争。我有一个相当标准的设置,使用CoreDataBook示例:我有一个RootView,它使用NSFetchedResultsController来显示项目列表。项具有一些属性以及与其他实体的关系。我有一个DetailView,我用它来创建一个新的项目,以及编辑一个现有的项目,我以模态的方式呈现。在DetailView:viewDidLoad中,我创建了一个新的managedObjectContext,希望在其中进行所有更改。。。如果用户按Save,我将保存此上下文并将更改合并回来;否则,如果用户按cancel,所有这些更改就会消失

“添加新项”部分工作正常,但当我选择该行以显示与现有项相同的DetailView时,其中一个关系(在调试器的RootView中显示为fine)在DetailView中显示时突然变为零。以下是在UITableView的DidSelectRowatineXpath中显示DetailView的代码:

    Item *managedObject = (Item *)[self.fetchedResultsController objectAtIndexPath:indexPath];
    DetailView *childController = [[DetailView alloc] initWithNibName:@"DetailView" bundle:nil];

    UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:childController];    

    childController.existingItem = managedObject;

    // ** Item's relationship to Title is not nil at this point
    [self presentModalViewController:navController animated:YES];
    // ** Item's relationship Title is now nil

    [childController release];
    [navController release];
DetailView控制器中没有任何异常情况会导致这种情况。事实上,它甚至没有机会造成任何伤害。。。一旦启动,existingItem.title关系就已经为零。[existingItem是DetailView的保留属性]

你知道我应该从哪里开始调查这件事吗?在过去的几个小时里我都快疯了。下面是DetailView viewDidLoad中的一些代码,但在调用该关系之前该关系为零:

    // Create a new managed object context
    NSManagedObjectContext *addingContext = [[NSManagedObjectContext alloc] init];
    self.addEditContext = addingContext;
    [addingContext release];
    [self.addEditContext setPersistentStoreCoordinator:[[appDelegate managedObjectContext] persistentStoreCoordinator]];

    if (!self.existingItem) {
        self.existingItem = [NSEntityDescription insertNewObjectForEntityForName:@"Item" inManagedObjectContext: self.addEditContext];

    }else{
        self.existingItem = (Item *)[self.addEditContext objectWithID:[self.existingItem  objectID]];
    }
通过从一些列表中选择来设置标题关系:

self.existingItem.title = selectedTitle;
在save:方法中,我保存addEditContext并将更改与appdelegate上下文合并:

    NSNotificationCenter *dnc = [NSNotificationCenter defaultCenter];
    [dnc addObserver:self selector:@selector(addControllerContextDidSave:) name:NSManagedObjectContextDidSaveNotification object: self.addEditContext];

    // Save the context.
    NSError *error = nil;
    if (![self.addEditContext save:&error]){
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    }

    [dnc removeObserver:self name:NSManagedObjectContextDidSaveNotification object:self.addEditContext];
    self.addEditContext = nil;
在addControllerContextDidSave中:

- (void)addControllerContextDidSave:(NSNotification*)saveNotification {
    id appDelegate = [[UIApplication sharedApplication] delegate];
    // Merging changes causes the fetched results controller to update its results
    [[appDelegate managedObjectContext] mergeChangesFromContextDidSaveNotification:saveNotification];   
}
因此,save:stuff对新项目很有效,但当该项目设置为existingItem并再次加载时,self.existingItem.title为nil。从视图控制器中显示的角度来看,它是零(即使在显示之前它不是零)。因此,在主上下文中,它会加载项目及其标题关系,但当标题出现在presentModalViewController:navController中时,它会突然消失

真奇怪。如果有人能对此有所了解,我们将不胜感激


更新:另一件需要提及的事情是,标题肯定会持久化到persistentStore中。每次我关闭并重新加载应用程序时,RootView都会显示正在设置的标题关系。我一选择行,关系就变为零

您的设计都是不必要的复杂和冗余。我认为这种关系显示为nil,因为您为
self.existingItem
属性分配了错误的类

首先,没有理由仅仅为同一前台线程上的另一个视图创建另一个上下文。只需将现有的上下文传递到下一个视图,就可以省去无功能原因地合并到上下文的麻烦

第二,这一块:

}else{
    self.existingItem = (Item *)[self.addEditContext objectWithID:[self.existingItem  objectID]];
}
。。。完全没有意义,因为您正在将
self.existingItem
设置为自身。你不妨写下:

self.existingItem = self.existingItem;
。。。因为一旦保存了对象,对象ID就会固定在持久存储中。如果对象尚未保存,则ID是临时的,其他上下文无论如何都无法找到它

问题最可能的原因是
existingItem
属性的定义。如果将其定义为
id
NSManagedObject
,则它不会响应
标题
选择器,并将返回nil。它将出错,但您已将其强制转换为
,因此编译器认为它将响应
对象将响应的所有消息


除非你知道你将强迫一个对象模仿另一个对象,否则不要使用cast。否则,您只是在为编译器创建隐藏错误的机会

谢谢你的评论。existingItem肯定设置为@property(保留,非原子)Item*existingItem,所以不是这样。我创建另一个上下文的原因是,我想让用户对现有项进行一系列更改(或在添加新项时),但页面上有一个取消按钮,以在用户决定时回滚所有内容。我觉得最简单的方法是创建一个单独的上下文,这样更改就不会影响主线程的上下文。有更好的方法吗?我还尝试使用NSUndoManager来跟踪和回滚更改,而不是使用多个上下文。但它也有同样的问题。RootView的didSelectRowAtIndexPath中的“title”关系很好,直到调用[self-presentModalViewController:navController animated:YES]时,它才从RootView和DetailView中消失。现在使用UndoManager,当编辑被取消时,标题将恢复到视图中,但它仍然不会显示在DetailView中(即使所有内容都在同一上下文中)。这是否表明我可能做错了什么?另外,我添加了另一个关系(1对1),它工作正常,并显示在DetailView中。标题关系是多对一的(从项目到标题…因此一个标题可以与多个项目关联,但每个项目都有一个标题)。我最终使用了所有临时变量,并将新对象插入到上下文中,然后在取消时删除它们。事实上,它比我尝试处理多个上下文时要混乱得多,但它至少可以可靠地工作。从概念上讲,我不明白为什么使用另一个上下文是有问题的。。。是否鼓励创建单独的上下文来处理不同的“草稿行”,特别是在处理多个线程时?那么,如果它仍然在主线程上,为什么会有什么不同呢?您可以使用不同的上下文,但实际上不能作为“草稿行”,尽管我以前见过这种描述。该API旨在使用撤销管理来实现您想要的功能。作为你的目标