本人去年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, m