2011-07-31 45 views
0

我正在努力与核心数据中的一些奇怪的行为。我有一个相当标准的设置,使用CoreDataBook示例:我有一个RootView,它使用NSFetchedResultsController来显示Items列表。项目与其他实体有几个属性和关系。我有一个DetailView,我用它来创建一个新的Item,以及编辑一个现有的Item,这是我以模态呈现的。在DetailView:viewDidLoad中,我创建了一个新的managedObjectContext,我想在其中进行所有更改...如果用户按下Save,则保存此上下文并将更改合并回来;否则,如果用户按下取消,所有这些更改都会消失。核心数据 - 关系零率意外

这项工作的“添加新项目”部分工作正常,但是当我选择行来调出一个现有的项目,其中一个关系(在调试器中显示罚款的RootView)突然变得相同的DetailView当它在DetailView中呈现时为零。下面是UITableView中的didSelectRowAtIndexPath方法来显示的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中的一些代码,但关系是零,甚至之前,它被称为:

self.existingItem.title = selectedTitle; 

在节省:

// 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]]; 
    } 

标题关系由一些列表中选择设置方法,我救在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对一个新Item有效,但是当它被设置为existingItem并再次加载时,self.existingItem.title为零。而且它在视图控制器中呈现的时间点是零(即使在呈现之前它不是零)。因此,在主要上下文中,它加载了Item,它的标题关系很好,但当presentModalViewController:navController中出现title时突然消失。

真的很奇怪。如果任何人都可以对此有所了解,那将会非常感激。

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

回答

1

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

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

其次,此块:

}else{ 
    self.existingItem = (Item *)[self.addEditContext objectWithID:[self.existingItem objectID]]; 
} 

...是完全没有意义的,因为你设置self.existingItem到自身。你也可以写下:

self.existingItem = self.existingItem; 

...因为对象被保存后,对象id被固定在持久存储中。如果对象没有被保存,则该ID是临时的,而其他上下文将无法找到它。

问题最可能的原因是existingItem属性的定义。如果您将其定义为idNSManagedObject,那么它将不会响应title选择器并返回nil。它会出错,但是你已经把它作为Item,所以编译器认为它会响应一个Item对象会的所有消息。

除非你知道你会强迫一个物体模仿另一个物体,否则不要使用cast。否则,你只是创造机会来隐藏编译器的错误。

+0

感谢您的意见。 existingItem肯定被设置为@property(retain,nonatomic)Item * existingItem,所以不是这样。我创建另一个上下文的原因是我想让用户对existingItem进行一些更改(或者添加新的时候),但是在页面上有一个取消按钮可以在用户决定时回滚所有内容。我觉得最简单的方法是创建一个单独的上下文,以便这些更改不会影响主线程的上下文。有一个更好的方法吗? –

+0

我也尝试使用NSUndoManager来跟踪和回滚更改,而不是多个上下文。但它也有同样的问题。 'title'关系在RootView的didSelectRowAtIndexPath中没有问题,直到它调用[self presentModalViewController:navController animated:YES]时,它就从RootView和DetailView中消失。现在使用UndoManager,当编辑被取消时,标题在视图上被恢复,但它仍然没有出现在DetailView中(即使一切都在同一个上下文中)。这是否表明我可能做错了什么? –

+0

此外,我添加了另一种关系(1对1),它可以正常工作并显示在DetailView中。标题关系是多对一的(从项目到标题...所以标题可以与多个项目关联,但每个项目都有一个标题)。 –