核心数据:父上下文和变更传播

时间:2013-10-18 14:43:24

标签: ios core-data

我在我的应用中设置了以下核心数据:

Persistent Store Coordinator
  ^ Background MOC (NSPrivateQueueConcurrencyType)
      ^ Main Queue MOC (NSMainQueueConcurrencyType)

这是初始化代码:

_backgroundContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[_backgroundContext setPersistentStoreCoordinator:self.coordinator];
_mainContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[_mainContext setParentContext:_backgroundContext];

我使用背景MOC导入大量数据。我还使用它在后台执行复杂的提取请求,然后将对象ID传递给主队列以使用这些ID获取对象。

这很有效。但是,我不知道如何让主队列MOC知道后台MOC中所做的更改。我知道如果我在主队列MOC上执行获取请求,它将获得更改,但这不是我想要的。

可以使用后台MOC发布的NSManagedObjectContextObjectsDidChangeNotification通知并在主队列MOC上调用mergeChangesFromContextDidSaveNotification:吗?这应该导致主队列MOC的NSManagedObjectContextObjectsDidChangeNotification通知被触发。我正在我的视图控制器中侦听此通知,并检查userInfo的更改并相应地重新显示数据。 我认为如果你有一个持久的商店协调员和两个附加的MOC,你通常会这样做。但是,当你有孩子/父母的情境时,我不确定这是否是正确的做法。

2 个答案:

答案 0 :(得分:4)

让主MOC使用私有父MOC进行异步I / O很好。但是,您不应将该父MOC用于代表主MOC执行后台工作的任何内容。这有很多原因(其中包括与瞬态对象ID相关的性能和讨厌问题)。

如果您想对商店进行后台更新,我建议这样做。

PSC <--+-- PrivateMOC <---- MainMOC
       |
       +-- BackgroundPrivateMOC

这将允许后台操作导致主MOC中断最少,同时允许共享PSC缓存。

现在,共享数据......

MainMOC应该监听并合并BackgroundPrivateMO中的DidSave通知。

BackgroundMOC可以侦听和合并来自PrivateMOC的DidSave通知。

这允许合并仅使用永久对象ID并优化性能。

答案 1 :(得分:3)

我会说听NSManagedObjectContextObjectsDidChangeNotification通知可能不是最佳解决方案。

我这样做的方式和工作方式如下。 这是主要的上下文创建:

_mainContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
_mainContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy;
_mainContext.persistentStoreCoordinator = _persistentStoreCoordinator;

以下是背景上下文创建:

_backgroundContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
_backgroundContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy;
_backgroundContext.parentContext = self.mainContext;

现在,后台上下文仅用于写入(或读取)对象(可能在后台线程中)。主上下文仅用于从主队列中读取。 保存在背景上下文应该如下:

__block BOOL saved = [_backgroundContext save:error];
if (saved && _backgroundContext.parentContext) {
    [_backgroundContext.parentContext performBlockAndWait:^{
        saved = [self.parentContext save:error];
    }];
}

此保存方法可确保将所有更改传播到主上下文。如果你在很多后台线程中做了很多工作,那就更熟悉performBlockAndWait:方法,它可以在上下文中互斥。

如果您希望收到有关对象更改的通知,则无需收听通知,只需设置NSFetchedResultsController并注册为其代理即可。