NSConcurrencyType 用于在同一队列上使用独立的 NSManagedObjectContexts
Posted
技术标签:
【中文标题】NSConcurrencyType 用于在同一队列上使用独立的 NSManagedObjectContexts【英文标题】:NSConcurrencyType for using independent NSManagedObjectContexts on the same queue 【发布时间】:2016-11-16 00:52:19 【问题描述】:在基于 CoreData 的应用程序中,我通过后台 NSOperation
处理导入。因为操作在操作队列上运行,所以我利用旧版NSConfinementConcurrencyType
与NSManagedObjectContext
一起工作。在此导入操作期间,我还访问了辅助数据库的NSManagedObjectContext
。由于它在操作队列上运行,所以它也使用线程限制并发类型。这多年来一直很好用,但 NSConfinementConcurrencyType
现在在 ios 9 中已被弃用。
看来我唯一的(非弃用)选项是使用NSPrivateQueueConcurrencyType
,在performBlock:
中为主要上下文执行导入,并包装对次要上下文的每次调用或来自次要上下文的NSManagedObject
s performBlockAndWait:
中的上下文。此外,我必须非常小心,不要触摸来自错误队列的其他上下文中的对象。
这一行:
primaryObject.attribute = secondaryObject.attribute;
更改如下:
id secondaryObjectAttributeValue = nil;
[secondaryContext performBlockAndWait:^
secondaryObjectAttributeValue = secondaryObject.attribute;
];
primaryObject.attribute = secondaryObjectAttributeValue;
有没有人有更好的选择来处理同一队列中的多个NSManagedObjectContext
s,而不使用NSConfinementConcurrencyType
或跳过这些乏味的performBlock:
箍?
【问题讨论】:
【参考方案1】:我的建议是使用私有队列上下文,但要稍微改变您的方法:
-
创建您的
NSOperation
子类
在main
中创建私有上下文
在 main 中的私有上下文上执行一个块
在块中调用处理实际导入的方法
将上下文保存在同一块中
退出区块
退出操作。
基本上,您的代码应该与之前相同,只是包装在 NSOperation
的 -main
方法内的 -performBlock:
中。
【讨论】:
【参考方案2】:这里的标准模式是通过 init 或属性将主上下文对象中对象的 objectID 传递给 NSOperation。然后在操作的main方法中创建后台上下文,然后在performBlock里面使用objectID属性将对象加载到后台上下文中,使用existingObjectWithID方法实现。
当您保存后台上下文时,可以使用通知和合并方法手动将更改合并回主上下文,或者使用您的应用委托中的此设置自动合并:
self.persistentContainer.viewContext.automaticallyMergesChangesFromParent = YES;
注意:当使用这种模式 be wary 时,以任何其他方式使用 objectID,例如获取。
【讨论】:
以上是关于NSConcurrencyType 用于在同一队列上使用独立的 NSManagedObjectContexts的主要内容,如果未能解决你的问题,请参考以下文章