<简书 — 刘小壮> http://www.jianshu.com/p/61b7a615508cios
到目前为止,已经将
CoreData
相关的知识点都讲完了。git在这篇文章中,主要讲一个
CoreData
第三方库-MagicalRecord
。目前为止这个第三方在Github
上有**9500+**的Star
,是全部CoreData
第三方库中使用最多、功能最全的。在文章的后面还会对CoreData
作一个总结,以及对本系列全部文章作一个总结。github文章中若有疏漏或错误,还请各位及时提出,谢谢!数据库
CoreData
是苹果自家推出的一个持久化框架,使用起来更加面向对象。可是在使用过程当中会出现大量代码,并且CoreData
学习曲线比较陡峭,若是掌握很差,在使用过程当中很容易形成其余问题。编程
国外开发者开源了一个基于CoreData
封装的第三方——MagicalRecord
,就像是FMDB
封装SQLite
同样,MagicalRecord
封装的CoreData
,使得原生的CoreData
更加容易使用。而且MagicalRecord
下降了CoreData
的使用门槛,不用去手动管理以前的PSC
、MOC
等对象。数据结构
根据Github
上MagicalRecord
的官方文档,MagicalRecord
的优势主要有三条:并发
1. 清理项目中CoreData
代码 2. 支持清晰、简单、一行式的查询操做 3. 当须要优化请求时,能够获取NSFetchRequest
进行修改app
将MagicalRecord
添加到项目中,和使用其余第三方同样,能够经过下载源码和CocoaPods
两种方式添加。框架
1. 从Github下载MagicalRecord源码,将源码直接拖到项目中,后续须要手动更新源码。性能
2. 也能够经过CocoaPods
安装MagicalRecord
,须要在Podfile
中加入下面命令,后续只须要经过命令来更新。
pod "MagicalRecord"
在以前建立新项目时,经过勾选"Use Core Data"
的方式添加CoreData
到项目中,会在AppDelegate
文件中生成大量CoreData
相关代码。若是是大型项目,被占用的位置是很重要的。而对于MagicalRecord
来讲,只须要两行代码便可。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // 初始化CoreData堆栈,也能够指定初始化某个CoreData堆栈 [MagicalRecord setupCoreDataStack]; return YES; } - (void)applicationWillTerminate:(UIApplication *)application { // 在应用退出时,应该调用cleanUp方法 [MagicalRecord cleanUp]; }
MagicalRecord
是支持CoreData
的.xcdatamodeld
文件的,使得CoreData
这一优势能够继续使用。创建数据结构时仍是像以前使用CoreData
同样,经过.xcdatamodeld
文件的方式创建。
CoreData
是支持iCloud
的,MagicalRecord
对iCloud
相关的操做也作了封装,只须要使用MagicalRecord+iCloud.h
类中提供的方法,就能够进行iCloud
相关的操做。
例以下面是MagicalRecord+iCloud.h
中的一个方法,须要将相关参数传入便可。
+ (void)setupCoreDataStackWithiCloudContainer:(NSString *)containerID localStoreNamed:(NSString *)localStore;
MagicalRecord
对上下文的管理和建立也比较全面,下面是MagicalRecord
提供的部分建立和获取上下文的代码。由于是给NSManagedObjectContext
添加的Category
,能够直接用NSManagedObjectContext
类调用,使用很是方便。
可是须要注意,虽然系统帮咱们管理了上下文对象,对于耗时操做仍然要放在后台线程中处理,而且在主线程中进行UI操做。
+ [NSManagedObjectContext MR_context] 设置默认的上下文为它的父级上下文,并发类型为NSPrivateQueueConcurrencyType + [NSManagedObjectContext MR_newMainQueueContext] 建立一个新的上下文,并发类型为NSMainQueueConcurrencyType + [NSManagedObjectContext MR_newPrivateQueueContext] 建立一个新的上下文,并发类型为NSPrivateQueueConcurrencyType + [NSManagedObjectContext MR_contextWithParent:] 建立一个新的上下文,容许自定义父级上下文,并发类型为NSPrivateQueueConcurrencyType + [NSManagedObjectContext MR_contextWithStoreCoordinator:] 建立一个新的上下文,并容许自定义持久化存储协调器,并发类型为NSPrivateQueueConcurrencyType + [NSManagedObjectContext MR_defaultContext] 获取默认上下文对象,项目中最基础的上下文对象,并发类型是NSMainQueueConcurrencyType
MagicalRecord
对NSManagedObject
添加了一个Category
,将增删改查等操做放在这个Category
中,使得这些操做能够直接被NSManagedObject
类及其子类调用。
.1. 增 对于托管模型的建立很是简单,不须要像以前还须要进行上下文的操做,如今这都是MagicalRecord
帮咱们完成的。
// 建立并插入到上下文中 Employee *emp = [Employee MR_createEntity];
.2. 删
// 从上下文中删除当前对象 [emp MR_deleteEntity];
.3. 改
// 获取一个上下文对象 NSManagedObjectContext *defaultContext = [NSManagedObjectContext MR_defaultContext]; // 在当前上下文环境中建立一个新的Employee对象 Employee *emp = [Employee MR_createEntityInContext:defaultContext]; emp.name = @"lxz"; emp.brithday = [NSDate date]; emp.height = @1.7; // 保存修改到当前上下文中 [defaultContext MR_saveToPersistentStoreAndWait];
.4. 查
// 执行查找操做,并设置排序条件 NSArray *empSorted = [Employee MR_findAllSortedBy:@"height" ascending:YES];
下面示例代码中,Employee
根据已有的employeeFilter
谓词对象,建立了employeeRequest
请求对象,并将请求对象作修改后,从MOC
中获取请求结果,实现自定义查找条件。
NSPredicate *employeeFilter = [NSPredicate predicateWithFormat:@"name LIKE %@", @"*lxz*"]; NSFetchRequest *employeeRequest = [Employee MR_requestAllWithPredicate:employeeFilter]; employeeRequest.fetchOffset = 10; employeeRequest.fetchLimit = 10; NSArray *employees = [Employee MR_executeFetchRequest:employeeRequest];
.1. 能够经过修改MR_LOGGING_DISABLED
预编译指令的值,控制log
打印。
#define MR_LOGGING_DISABLED 1
.2.MagicalRecord
在DEBUG
模式下,对模型文件发生了更改,而且没有建立新的模型文件版本。MagicalRecord
默认会将旧的持久化存储删除,建立新的持久化存储。
MagicalRecord
的使用方法还有不少,这里只是将一些比较经常使用的拿出来说讲,其余就不一一讲解了。在Github
上有国人翻译的MagicalRecord
官方文档,翻译的很是全面,并且是实时更新的。
这篇文章关于MagicalRecord
的部分,也是参考文章来写的,我这里就犯了个懒。。。
不管是什么东西,确定不会是绝对完美的,CoreData
也是如此。CoreData
被设计出来后,对比其余本地持久化方案有本身独有的优点,也有比较严重的问题。
对于一个本地持久化方案的选取,仍是要根据公司业务需求,来选择一个适合项目的方案,并无哪一个方案是万能的。
能够设置关联关系,也就是以前讲过的关联属性,关联属性能够和当前对象一块儿被MOC
操做。 例如Company
关联一个Person
对象,对Company
进行操做时,也能够经过点语法从Company
中获取Person
,Person
的修改会随着Company
一块儿被持久化。 若是用SQLite
实现起来是很麻烦的,但CoreData
能够很容易的完成,这也是CoreData
更加面向对象的一种体现。
更加面向对象,将以前Model
层的表示和持久化合二为一。把数据库的交互和对象的转换封装起来,使用时不须要接触到任何SQLite
相关的代码,直接使用托管对象便可。
开发效率比较快,能够很快的封装一个基于CoreData
实现的Model
层,而不须要太多的代码就能够实现。
能够很好的防范SQL注入
的问题。对于SQLite
来讲,若是是用FMDB
而且用?占位符
,也能够防范SQL注入
的问题。
可视化化效果好且结构清晰。将模型文件内部的结构,以及实体之间的对应关系等,以可视化的结构展示出来。
对OC
原生编程支持很是好,支持keyPath
操做方式。例如设置NSPredicate
查找条件时,可使用keyPath
的点语法设置属性。而其余持久化存储对于这点支持的不太好,须要编写很复杂的查找条件,看起来也不太好理解。 毕竟是Apple
自家推出的,因此对OC
融合度比较高,能够很好的配合和使用OC
对象。
设置一对一或一对多的关系,设置关系后作存储和查询也很是方便,这是很是便于开发的。若是对于性能没有苛刻的要求,而且持久化对象之间关系比较复杂,比较推荐使用CoreData
。
灵活性不如SQLite
,CoreData
是对SQLite
的一个封装,上层不能直接对数据库进行操做。处理任何数据都要按照CoreData
内部的实现逻辑执行,而不能自定义执行逻辑,对执行逻辑没有可控性。
进行大量数据处理时比较吃力,性能明显低于直接操做SQLite
数据库,并且内存占用很是大,须要手动作内存控制。 当执行一个操做时涉及的数据比较多,须要将全部相关的托管对象加载到内存中,并且中间还涉及到对象的转换等操做。这样对性能和内存的消耗都是很是大的,和涉及到的数据量成正比。
由于CoreData
底层是用SQLite
实现的,能够在CoreData
的基础上,直接编写SQL语句
对数据库进行操做。可是并不推荐这样作,在一个项目中应该只有一种持久化的主体方案。并且若是这两种方式混用的话,对于后期维护是很是困难的。 若是出现这样的需求,最好直接去用SQLite。
CoreData入门门槛比较高,很难很好的掌握。 不少人都说CoreData
很差用,这个缘由很大一部分都是由于使用方式的问题。CoreData
框架学习难度比较大,致使不少人都只是简单的使用CoreData
,这些用法不少都是不合理的,不少的高级用法并无用到。
到目前为止CoreData
系列的六篇文章就都写完了,文章中可能存在一些没有注意的问题,还请各位提出。博客中包括CoreData
在内的全部文章永久更新维护,会不断将新知识添加到对应的文章中,也会对落后的文章进行重写。
在第一篇文章中也说到,我接触CoreData
时间也不是很长,这系列文章更像是我学习的一个总结。可是我确实是很认真的在写,文章内容也是检查了不少遍,防止错字或者语法问题。知识点总结的仍是比较全面的,在后续我还会更深刻的学习CoreData
,也可能会推出后续文章。
许多人对于CoreData
有不少意见,认为CoreData
有各类各样的问题,这并非空穴来风。在我学习CoreData
的过程当中,也发现CoreData
确实存在诸多问题,例如查询性能略差、灵活性等。因此在使用CoreData
的时候,仍是根据公司业务需求来权衡是否使用CoreData
。
好多同窗都问我有Demo
没有,其实文章中贴出的代码组合起来就是个Demo
。后来想了想,仍是给本系列文章配了一个简单的Demo
,方便你们运行调试,后续会给全部博客的文章都加上Demo
。
Demo
只是来辅助读者更好的理解文章中的内容,应该博客结合Demo
一块儿学习,只看Demo
仍是不能理解更深层的原理。Demo
中几乎每一行代码都会有注释,各位能够打断点跟着Demo
执行流程走一遍,看看各个阶段变量的值。
Demo地址:刘小壮的Github
这两天更新了一下文章,将CoreData
系列的六篇文章整合在一块儿,作了一个PDF
版的《CoreData Book》,放在我Github上了。PDF
上有文章目录,方便阅读。
若是你以为不错,请把PDF帮忙转到其余群里,或者你的朋友,让更多的人了解CoreData,衷心感谢!