<简书 — 刘小壮> http://www.jianshu.com/p/61b7a615508cios
到目前为止,已经将CoreData
相关的知识点都讲完了。在这篇文章中,主要讲一个
CoreData
第三方库-MagicalRecord
。目前为止这个第三方在Github
上有9500+的Star
,是全部CoreData
第三方库中使用最多、功能最全的。在文章的后面还会对CoreData
作一个总结,以及对本系列全部文章作一个总结。git文章中若有疏漏或错误,还请各位及时提出,谢谢!😊github
CoreData
是苹果自家推出的一个持久化框架,使用起来更加面向对象。可是在使用过程当中会出现大量代码,并且CoreData
学习曲线比较陡峭,若是掌握很差,在使用过程当中很容易形成其余问题。数据库
国外开发者开源了一个基于CoreData
封装的第三方——MagicalRecord
,就像是FMDB
封装SQLite
同样,MagicalRecord
封装的CoreData
,使得原生的CoreData
更加容易使用。而且MagicalRecord
下降了CoreData
的使用门槛,不用去手动管理以前的PSC
、MOC
等对象。编程
根据Github
上MagicalRecord
的官方文档,MagicalRecord
的优势主要有三条:数据结构
1. 清理项目中CoreData
代码
2. 支持清晰、简单、一行式的查询操做
3. 当须要优化请求时,能够获取NSFetchRequest
进行修改并发
将MagicalRecord
添加到项目中,和使用其余第三方同样,能够经过下载源码和CocoaPods
两种方式添加。app
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
。
好多同窗都问我有Demo
没有,其实文章中贴出的代码组合起来就是个Demo
。后来想了想,仍是给本系列文章配了一个简单的Demo
,方便你们运行调试,后续会给全部博客的文章都加上Demo
。
Demo
只是来辅助读者更好的理解文章中的内容,应该博客结合Demo
一块儿学习,只看Demo
仍是不能理解更深层的原理。Demo
中几乎每一行代码都会有注释,各位能够打断点跟着Demo
执行流程走一遍,看看各个阶段变量的值。
Demo地址:刘小壮的Github
这两天更新了一下文章,将CoreData
系列的六篇文章整合在一块儿,作了一个PDF
版的《CoreData Book》,放在我Github上了。PDF
上有文章目录,方便阅读。
若是你以为不错,请把PDF帮忙转到其余群里,或者你的朋友,让更多的人了解CoreData,衷心感谢!😁