原文地址:http://blog.csdn.net/willmomo/article/details/19759413

写的非常好!我这里截取一点重要的,备份,请去原地址阅读!

本人去年10月份才接触IOS项目的,项目中用到了CoreData,由于需要调用子线程进行API请求,所以需要在子线程中使用NSManagedObjectContext进行数据的增删改查。因此当时百度了很多相关东西,但是没有得到我要的答案,后来硬着头皮Google了很多英文博客和论坛(本人英文水平其实还可以,英文文档看起来也没那么吃力,但总归不是母语,到现在都有一种抵触感),研究的也是一知半解,由于项目进度不能耽搁,也没有深究,最后选用了persistentStoreCoordinator<-mainContext<-privateContext这样的结构,让我完成了需求。

由于刚过完年,手头上的工作不多,想着重构一下之前写的代码。由于之前CoreData的代码虽然让我完成了项目需求,但是始终没有让我感到有安全感,所以重构代码的第一件事就是好好研究CoreData。在Google的时候,我发现了这样两篇老外的博客(http://floriankugler.com/blog/2013/4/2/the-concurrent-core-data-stack,http://floriankugler.com/blog/2013/4/29/concurrent-core-data-stack-performance-shootout)。前者是介绍NSManagedObjectContext在多线程下的三种设计,后者是博主对这三种设计进行的性能测试。下面我将一一介绍:

1. persistentStoreCoordinator<-mainContext<-privateContext

这种设计就是我之前在项目中使用的,也是阻塞UI线程最严重的一种设计。它总共有两个Context,一个是UI线程中使用的mainContext,一个是子线程中使用的privateContext,他们的关系是privateContext.parentContext = mainContext,而mainContext是与Disk连接的Context,所以这种设计下,每当子线程privateContext进行save操作以后,它会将数据库所有变动Push up到其父Context,也就是mainContext中去,注意:这时子线程的save操作并没有任何关于Disk IO的操作。而后mainContext在UI线程又要执行一次save操作才能真正将数据变动写进数据库中,这里的save操作就与Disk IO有关了,而且又是在主线程,所以说这种设计是最阻碍UI线程的。

2. persistentStoreCoordinator<-backgroundContext<-mainContext<-privateContext

这种设计是第一种的改进设计,也是上述的老外博主推荐的一种设计方式。它总共有三个Context,一是连接persistentStoreCoordinator也是最底层的backgroundContext,二是UI线程的mainContext,三是子线程的privateContext,后两个Context在1中已经介绍过了,这里就不再具体介绍,他们的关系是privateContext.parentContext = mainContext, mainContext.parentContext = backgroundContext。下面说说它的具体工作流程。

在应用中,如果我们有API操作,首先我们会起一个子线程进行API请求,在得到Response后要进行数据库操作,这是我们要创建一个privateContext进行数据的增删改查,然后call privateContext的save方法进行存储,这里的save操作只是将所有数据变动Push up到它的父Context中也就是mainContext中,然后mainContext继续call save方法,将数据变动Push up到它的父Context中也就是backgroundContext,最后调用backgroundContext的save方法真正将数据变动存储到Disk数据库中,在这个过程中,前两个save操作相对耗时较少,真正耗时的操作是最后backgroundContext的save操作,因为只有它有Disk IO的操作。

3. persistentStoreCoordinator<-mainContext

persistentStoreCoordinator<-privateContext

第三种设计是最直观的一种设计,无论是mainContext还是privateContext都是连接persistentStoreCoordinator的。这种设计的工作流程是:

首先在ViewController中要添加一个名为NSManagedObjectContextDidSaveNotification的通知
,然后子线程中创建privateContext,进行数据增删改查操作,直接save到本地数据库,这时在ViewController中会回调之前注册的NSManagedObjectContextDidSaveNotification的回调方法,在该方法中调用mainContext的mergeChangesFromContextDidSaveNotification:notification方法,将所有的数据变动merge到mainContext中,这样就保持了两个Context中的数据同步。由于大部分的操作都是privateContext在子线程中操作的,所以这种设计是UI线程耗时最少的一种设计,但是它的代价是需要多写mergeChanges的方法。(注:前两种parent,child的Context,一旦childContext调用save方法,其parentContext不用任何merge操作,CoreData自动将数据merge到parentContext当中)

总结:

第一种设计是失败的设计,完全可以不考虑,第二种设计比较复杂繁琐,但是它是最方便而且UI线程的阻塞时间也是相对较少的一种。第三种设计是最少阻塞UI的一种,但是这种设计操作比较繁琐,应用场合是数据量比较大的应用,一般会应用在企业应用中,所以如果你不是企业级的应用或者不是数据量很大的应用,我还是推荐第二种设计。我根据第二种设计写了一个Demo,下面附上一些关键代码供大家参考:

注:在参考代码之前大家可能要对NSManagedObjectContext的concurrencyType有所了解,还有就是performBlock和performBlockAndWait:方法的区别。

Core Data 多线程时多个context使用的更多相关文章

  1. 正确使用Core Data多线程的3种方式

    在#Pragma Conference 2015会议上,Marcus Zarra,撰写过关于Core Data和Core Animation的书,叙述了三种在多线程环境下使用Core Data的方法并 ...

  2. iOS Core data多线程并发访问的问题

    大家都知道Core data本身并不是一个并发安全的架构:不过针对多线程访问带来的问题,Apple给出了很多指导:同时很多第三方的开发者也贡献了很多解决方法.不过最近碰到的一个问题很奇怪,觉得有一定的 ...

  3. iOS开发中的4种数据持久化方式【二、数据库 SQLite3、Core Data 的运用】

                   在上文,我们介绍了ios开发中的其中2种数据持久化方式:属性列表.归档解档.本节将继续介绍另外2种iOS持久化数据的方法:数据库 SQLite3.Core Data 的运 ...

  4. 我为什么用 SQLite 和 FMDB 而不用 Core Data

    凭良心讲,我不能告诉你不去使用Core Data.它不错,而且也在变好,并且它被很多其他Cocoa开发者所理解,当有新人加入你的组或者需要别人接手你的项目的时候,这点很重要.更重要的是,不值得花时间和 ...

  5. 四种数据持久化方式(下) :SQLite3 和 Core Data

    在上文,我们介绍了iOS开发中的其中2种数据持久化方式:属性列表.归档解档. 本节将继续介绍另外2种iOS持久化数据的方法:数据库 SQLite3.Core Data 的运用: 在本节,将通过对4个文 ...

  6. 关于Core Data的一些整理(三)

    关于Core Data的一些整理(三) 关于Core Data Stack的四种类与它们的关系如下: NSManagedObjectModel NSPersistentStore NSPersiste ...

  7. 谈谈用SQLite和FMDB而不用Core Data

    谈谈用SQLite和FMDB而不用Core Data 发布于:2014-04-22 11:22阅读数:4235 凭良心讲,我不能告诉你不去使用Core Data.它不错,而且也在变好,并且它被很多其他 ...

  8. 用 SQLite 和 FMDB 替代 Core Data

    本文转载至 http://blog.csdn.net/majiakun1/article/details/38680147 为什么我不使用Core Data Mike Ash 写到: 就个人而言,我不 ...

  9. #译# Core Data概述 (转)

    昨晚熬夜看发布会(本以为屌丝终于能买得起苹果了,谁知道...),因为看不了视频直播,所以就正好有空就把www.objc.io最新的一篇文章翻译了一下,同时感谢CocoaChina翻译组提供校对,以下为 ...

随机推荐

  1. 我的linux桌面

    经过几次尝试安装linux系统之后,终于把自己的系统安装成了linux系统. wangkongming@ThinkPad-T410 ~ $ lsb_release -a No LSB modules ...

  2. Subversion命令汇总

    转自:http://www.cnblogs.com/cnblogsfans/archive/2010/03/21/1690838.html svn 命令共同的选项 --targets list 读取l ...

  3. vim 打开Linux下文件每一行后面都有^M的样式

    由于服务器不是我一个人在操作,在修改apache配置文件时发现了一个很奇怪的问题,vim编辑打开配置文件发现后面都有一个^M的标记 虽然不会影响服务的运行,但总感觉不对劲,所以在此我尝试用替换的方式来 ...

  4. app的meta

    <meta http-equiv="content-type" content="text/html; charset=UTF-8" /> < ...

  5. Java-Linux系统中搭建开发环境

    准备工作: 0.虚拟机中的系统→{RHEL-I386} 1.JDK→{首先要知道下载哪个版本" [zf@string ~]$ getconf LONG_BIT ":".t ...

  6. 繁华模拟赛day8 字典序

    /* 这个题要我们求一个字典序,字符串给出的顺序,会对字母的字典序前后相对顺序进行限定,如何用来表示这种限定,我们注意到这种一个之后接着一个,只有先输出他前面的才能输出他,很明显就是拓扑排序,最小方案 ...

  7. PHP安装laravel(win+linux)

    作为一名不优秀的程序猿,忙碌的四月终于结束了,五一大假的最后一天,终于有时间来整理整理这段时间的收获了. 一.laravel介绍 首先看看http://www.sitepoint.com/网站做的一个 ...

  8. PHP封装一个通用好用的文件上传处理类

    封装一个文件上传类完成基本功能如下: 1.可上传多个或单个文件 2.上传成功返回一个或多个文件名 3.上传失败则返回每个失败文件的错误信息 上传类中的基本功能: 1.构造参数,用户可以自定义配置参数, ...

  9. Logistic 回归(sigmoid函数,手机的评价,梯度上升,批处理梯度,随机梯度,从疝气病症预测病马的死亡率

    (手机的颜色,大小,用户体验来加权统计总体的值)极大似然估计MLE 1.Logistic回归 Logistic regression (逻辑回归),是一种分类方法,用于二分类问题(即输出只有两种).如 ...

  10. Apache常用2种工作模式prefork和worker比较

    Apache两种常用工作模式:prefork和worker. prefork MPM prefork是一个非线程型的.预派生的MPM,使用多个进程,每个进程在某个确定的时间只单独处理一个连接,效率高, ...