为何使用多线程
在开发中使用到了CoreData,虽然实例化NSManagedObjectContext的时候提供了三种方法:
NSConfinementConcurrencyType(iOS 9废弃)
NSPrivateQueueConcurrencyType
NSMainQueueConcurrencyType
NSManagedObjectContext提供的多线程执行方法:
-(void)performBlock:(void(^)())blockNS_AVAILABLE(10_7,5_0);
-(void)performBlockAndWait:(void(^)())blockNS_AVAILABLE(10_7,5_0);
但在实际使用中,如果线程方法有问题,一样可能会导致数据库读写操作等问题,比如读写同时操作导致数据源为空等。找了很多文档,分享下使用方案。
多线程方案
通过建立上下文间的父子关系,避免上下文的合并操作。
子上下文的改动保存时会提交给父上下文,最后由根部的上下文提交所有改动给PSC。因此建立关系之后,上下文的改动就不需要用通知去告知其他上下文了。我们可以通过设置如下属性来设置父上下文。
使用三层的MOC去实现多线程Core Data,privateContext -> mainContext -> rootContext。
其中privateContext用于执行操作,mainContext用于与UI协作,rootContext用于在后台保存所有子上下文的提交。
存在的问题
MO都有唯一的MOID与之对应,为了避免实例化MO时消耗大量资源来确保ID的唯一性,所以MO在实例化时会被给予一个临时的ID,这个ID在MOC范围内唯一。当MOC进行提交时,需要将临时ID转化为全局ID,所以我们需要监听MOC将要保存的通知来处理MOID的转换:
// 上下文将要提交保存的通知
nameNSManagedObjectContextWillSaveNotification
// MOID转换方法
- (BOOL)obtainPermanentIDsForObjects:(NSArray *)objects error:(NSError**)errorNS_AVAILABLE(10_5,3_0);
方案二初始化:
CoreDataManager.m:
增:
删:
改:
查:
总结
在一般的数据库操作时,数据修改放在privateContext异步执行,数据查询放在MainContext同步执行,保证数据正确。但是特殊的情况(比如我遇到的项目),所有操作必须要在启动数据库修改完成后执行,那么数据库修改要放到MainContext执行。
相关参考链接:链接
网友评论