7

我的应用程序中有以下核心数据设置:

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 上执行提取请求,它将获得更改,但这不是我想要的。

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

4

2 回答 2

6

Having the main MOC use a private parent MOC for asynchronous I/O is fine. However, you should not use that parent MOC for anything but performing background work on behalf of the main MOC. There are many reasons for this (among them performance and nasty issues related to transient object IDs).

If you want to do background updating of the store, here is what I suggest.

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

This will allow background operation that causes the least interruption to the main MOC, while allowing the PSC caches to be shared.

Now, for sharing data...

The MainMOC should listen for and merge DidSave notifications from the BackgroundPrivateMO.

The BackgroundMOC can listen for and merge DidSave notifications from the PrivateMOC.

This allows merging to use only permanent object IDs and optimizes performance.

于 2014-03-03T20:52:56.117 回答
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并注册为其委托。

于 2013-10-18T15:18:01.987 回答