核心数据:父上下文和变更传播
Posted
技术标签:
【中文标题】核心数据:父上下文和变更传播【英文标题】:Core Data: Parent context and change propagation 【发布时间】:2013-10-18 14:43:23 【问题描述】:我的应用中有以下核心数据设置:
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 上执行 fetch 请求,它将获得更改,但这不是我想要的。
使用后台MOC发布的NSManagedObjectContextObjectsDidChangeNotification
通知,在主队列MOC上调用mergeChangesFromContextDidSaveNotification:
可以吗?这应该会导致主队列 MOC 的NSManagedObjectContextObjectsDidChangeNotification
通知触发。我正在我的视图控制器中收听此通知,并检查userInfo
的更改并相应地重新显示数据。
如果您有一个带有两个附加 MOC 的持久存储协调器,我认为您通常会这样做。但是当您有子/父上下文时,我不确定这是否是正确的方法。
【问题讨论】:
【参考方案1】:让主 MOC 使用私有父 MOC 进行异步 I/O 很好。但是,除了代表主 MOC 执行后台工作之外,您不应将该父 MOC 用于其他任何事情。造成这种情况的原因有很多(其中包括与瞬态对象 ID 相关的性能和令人讨厌的问题)。
如果您想对商店进行后台更新,我建议您这样做。
PSC <--+-- PrivateMOC <---- MainMOC
|
+-- BackgroundPrivateMOC
这将允许对主 MOC 造成最小中断的后台操作,同时允许共享 PSC 缓存。
现在,为了共享数据...
MainMOC 应该监听并合并来自 BackgroundPrivateMO 的 DidSave 通知。
BackgroundMOC 可以监听并合并来自 PrivateMOC 的 DidSave 通知。
这允许合并仅使用永久对象 ID 并优化性能。
【讨论】:
是否可以将 BGPrivateMOC 作为 mainMOC 的子节点并通过保存 BGPrivateMOC 来传播所有 BG 更改?我试过这样做,但我的 mainMOC 没有从 BGPrivateMOC 得到任何更改。决定试试你的堆栈。它就像一个魅力。 哦,出了点问题,它不再起作用了。合并不会更新主上下文。 您需要提供比这更多的详细信息...也许输入一个新问题,其中包含有关您的特定问题的详细信息...如果您希望我看到它,可以在此处评论该问题... 是的,一旦我准备好示例代码,我会给你一个指向我的问题的链接 嗨,请检查这个问题***.com/questions/28520133/…【参考方案2】:我想说收听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
并注册为其委托。
【讨论】:
以上是关于核心数据:父上下文和变更传播的主要内容,如果未能解决你的问题,请参考以下文章