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

Flo*_*ian 7 core-data ios

我的应用程序中有以下Core Data设置:

Persistent Store Coordinator
  ^ Background MOC (NSPrivateQueueConcurrencyType)
      ^ Main Queue MOC (NSMainQueueConcurrencyType)
Run Code Online (Sandbox Code Playgroud)

这是初始化代码:

_backgroundContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[_backgroundContext setPersistentStoreCoordinator:self.coordinator];
_mainContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[_mainContext setParentContext:_backgroundContext];
Run Code Online (Sandbox Code Playgroud)

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

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

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

Jod*_*ins 6

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

如果你想做商店的后台更新,这是我的建议。

PSC <--+-- PrivateMOC <---- MainMOC
       |
       +-- BackgroundPrivateMOC
Run Code Online (Sandbox Code Playgroud)

这将允许对主 MOC 造成最少中断的后台操作,同时允许共享 PSC 缓存。

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

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

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

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


Mac*_*zko 3

我想说听NSManagedObjectContextObjectsDidChangeNotification通知可能不是最好的解决方案。

我的做法及其工作原理如下。这是主要上下文创建:

_mainContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
_mainContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy;
_mainContext.persistentStoreCoordinator = _persistentStoreCoordinator;
Run Code Online (Sandbox Code Playgroud)

这是后台上下文创建:

_backgroundContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
_backgroundContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy;
_backgroundContext.parentContext = self.mainContext;
Run Code Online (Sandbox Code Playgroud)

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

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

此保存方法保证所有更改都将传播到主上下文。如果您在许多后台线程中做了很多工作,就会更加熟悉performBlockAndWait:方法,它提供了上下文上的互斥。

如果您想收到有关对象更改的通知,则不必监听通知,只需设置NSFetchedResultsController并注册为其委托即可。