3

我今天对我的发现感到非常困惑。

我认为只要所有上下文都使用相同的 Core Data 持久存储,一个上下文中的任何更改都应该在保存上下文后出现在另一个上下文中。

例如,在视图控制器 AI 中有 1 个上下文(上下文 A),在视图控制器 B 中,我有另一个上下文(上下文 B)。现在上下文 A 和上下文 B 都指向同一个持久存储。

在上下文 A 中,我从持久存储中获取了一个托管对象,更新了托管对象的一个​​属性,然后使用 managedObjectContext 保存操作将更改保存回持久存储。

现在我打开我的第二个视图控制器并从同一个持久存储执行一个获取请求,但我的第二个视图控制器没有看到更新的属性更改,直到我重新启动模拟器。

真正奇怪的是,如果这是我第一次将新的托管对象插入到持久存储中,控制器 B 会看到更改,但不会显示后续更改。

经过长时间的战斗,我已经解决了这个问题,我只想知道为什么有两个单独的上下文(当然都在主线程上)共享同一个持久存储在模拟器重新启动之前不会看到更改。

对于那些想知道我如何修复它的人,在我的基本视图控制器中,控制器 A 和 B 都继承自哪个控制器,而不是分配初始化一个新上下文(因此控制器 A 和 B 有两个单独的上下文),我告诉基础视图控制器引用应用程序委托中的上下文(因此,控制器 A 和 B 现在指向相同的上下文)。

这是解释我所看到的图表:

在此处输入图像描述

在第二个视图控制器中获取的结果值是旧值。

如果我将一些数据提交到持久存储,只要我从同一个持久存储中获取,它就应该成为永久的并且可以在任何地方访问,除非我误解了 managedObjectContext save: 实际上并没有立即对持久存储进行更改,直到应用结果。

4

1 回答 1

1

张,

没有细节很难找出问题所在。

一个简单的建议是验证您是否合并了应用程序中两个不同上下文之间的更改。换句话说,您需要验证主上下文合并来自另一个上下文的更改。这可以像下面这样简单地实现。

例如,在您AppDelegate或您正在创建 Core Data 堆栈的位置注册此通知。

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contextChanged:) name:NSManagedObjectContextDidSaveNotification object:nil];

实现 contextChanged: 方法来合并更改。

- (void)contextChanged:(NSNotification*)notification
{
    if ([notification object] == [self managedObjectContext])
        return;

    if (![NSThread isMainThread]) {
        [self performSelectorOnMainThread:@selector(contextChanged:) withObject:notification waitUntilDone:YES];
        return;
    }

    [[self managedObjectContext] mergeChangesFromContextDidSaveNotification:notification];
}

有关详细信息,请参阅Marcus Zarra 教程

此外,如果您结合使用表,NSFetchedResultsController请记住实现委托的方法。有关信息,请参阅NSFetchedResultsControllerDelegate类。

希望有帮助。

于 2012-09-08T11:16:04.603 回答