我的应用程序中有以下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,你通常会这样做.但是,当你有孩子/父母的情境时,我不确定这是否是正确的做法.
让主 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 并优化性能。
我想说听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并注册为其委托即可。
| 归档时间: |
|
| 查看次数: |
5043 次 |
| 最近记录: |