<简书 — 刘小壮> http://www.jianshu.com/p/c0e12a897971git
这段时间公司一直比较忙,和组里小伙伴一块儿把公司项目按照以前逻辑重写了一下。因为项目比较大,还要兼顾以前项目的迭代和其余项目,目前为止只写完第一阶段。 以前项目本地持久化方案主要用的是SQLite,此次重写项目打算换一种持久化方案,因而咱们通过讨论选择了苹果的“亲儿子”CoreData。 在使用CoreData的过程当中,我也是一边学习一边实践。在学习的过程当中,一些写的质量比较高的博客对个人帮助也很大,例如objc.io等博客,在这里就不一一列举出来了,很是感谢这些做者。
程序员
先不说项目中用不用获得,其实不少人都是不了解CoreData的,可是通过个人学习发现CoreData仍是挺不错的。因此正如这系列文章的名字同样-认识CoreData,打算写这系列文章来认识一下CoreData。 这系列博客将从简单到复杂的来说一下CoreData,其中除了基础使用还会包括多线程、批量数据处理等内容,这些不少都是我公司项目开发过程当中接触到的,咱们也设想了一些极端的状况,解决方案都会体如今这系列博客中。
github
本人接触CoreData时间并不长,只是专门花了一段时间学习CoreData。 本系列文章偏重于经过图形化界面使用CoreData,不会所有采起纯代码进行CoreData的全部操做,并且那样操做起来也确实比较麻烦,反而就失去了CoreData的优点和本质。
sql
文章中若有疏漏或错误,还请各位及时提出,谢谢!
数据库
在CoreData
中有一些经常使用的类,称呼可能各不相同。因此这里先约定一些关键字,以便理解后面的一些内容,这些约定不少都是出如今苹果的官方文档中的。 NSPersistentStoreCoordinator
(Persistent Store Coordinator),缩写为PSC。 NSManagedObjectContext
(Managed Object Context),缩写为MOC。 NSManagedObjectModel
(Managed Object Model),缩写为MOM。 NSManagedObject
及其子类,根据英文翻译和其做用,称之为托管对象。 后缀名为.xcdatamodeld
的文件,由于存储着全部实体的数据结构和表示,因此称之为模型文件。缓存
CoreData
出如今iOS3
中,是苹果推出的一个数据存储框架。CoreData
提供了一种对象关系映射(ORM
)的存储关系,相似于Java
的hibernate框架。CoreData
能够将OC
对象存储到数据库中,也能够将数据库中的数据转化为OC
对象,在这个过程当中不须要手动编写任何SQL
语句,这是系统帮咱们完成。安全
CoreData
最大的优点就是使用过程当中不须要编写任何SQL
语句,CoreData
封装了数据库的操做过程,以及数据库中数据和OC
对象的转换过程。因此在使用CoreData
的过程当中,不少操做就像是对数据库进行操做同样,也有过滤条件、排序等操做。服务器
这就至关于CoreData
完成了Model
层的大量工做,例如Model
层的表示和持久化,有效的减小了开发的工做量,使Model
层的设计更加面向对象。数据结构
以前听人说过,CoreData
比较容易入手,可是很难学精。这也是不少人说CoreData
很差用的缘由之一,只是由于使用方式有问题,或者说并无真正掌握CoreData
。多线程
若是从性能上来讲,CoreData
比SQLite
确实略差一些。可是对于移动端来讲,并不须要大型网站的高并发,因此这点性能差异几乎是没有影响的,因此这点能够忽略不计。在后面的文章中,将会给出CoreData
的优势和缺点对比,以及详细的性能测评。
.xcdatamodeld
),存储着数据库的数据结构。CoreData
中的托管对象都必须继承自当前类,根据实体建立托管对象类文件。模型文件操做 1.1 建立模型文件,后缀名为.xcdatamodeld
。建立模型文件以后,能够在其内部进行添加实体等操做(用于表示数据库文件的数据结构) 1.2 添加实体(表示数据库文件中的表结构),添加实体后须要经过实体,来建立托管对象类文件。 1.3 添加属性并设置类型,能够在属性的右侧面板中设置默认值等选项。(每种数据类型设置选项是不一样的) 1.4 建立获取请求模板、设置配置模板等。 1.5 根据指定实体,建立托管对象类文件(基于NSManagedObject
的类文件)
实例化上下文对象 2.1 建立托管对象上下文(NSManagedObjectContext
) 2.2 建立托管对象模型(NSManagedObjectModel
) 2.3 根据托管对象模型,建立持久化存储协调器(NSPersistentStoreCoordinator
) 2.4 关联并建立本地数据库文件,并返回持久化存储对象(NSPersistentStore
) 2.5 将持久化存储协调器赋值给托管对象上下文,完成基本建立。
以前看到过几张介绍CoreData
结构的图片,感受其表示的结构比较清晰。能够经过这几张图片初步认识一下CoreData
,在后面的文章中还会对这几个类进行详细解释。
上图中是初始化MOC
所涉及到的一些类,由这些类实例化并最终构成可使用的MOC
。图中编号是实例化一个具有数据处理能力的MOC
过程,这个过程和上面介绍过的实例化上下文对象相同。
在PSC
建立并关联本地数据库,并设置为MOC
的persistentStoreCoordinator
属性后,MOC
就具有对当前存储区全部托管对象操做的能力。可是须要注意的是,MOC
对托管对象是懒加载的,在使用时才会被加载到MOC
的缓存中。
MOM
对象加载模型文件后,获取到模型文件中全部实体的构成结构。因为MOM
中存储着模型文件的结构,PSC
须要经过MOM
对象实例化本地数据库。
全部属性都存在Entity
中,以及有关联关系的属性和请求模板,这都会在后面的章节中讲到。
能够经过Entity
建立继承自NSManagedObject
类的文件,这个文件就是开发中使用的托管对象,具有模型对象的表示功能,CoreData
的本地持久化都是经过这个类及其子类完成的。
在CoreData
的总体结构中,主要分为两部分。一个是NSManagedObjectContext
管理的模型部分,管理着全部CoreData
的托管对象。一个是SQLite
实现的本地持久化部分,负责和SQL
数据库进行数据交互,主要由NSPersistentStore
类操做。这就构成了CoreData
的大致结构。
从图中能够看出,这两部分都是比较独立的,两部分的交互由一个持久化存储调度器(NSPersistentStoreCoordinator
)来控制。上层NSManagedObjectContext
存储的数据都是交给持久化调度器,由调度器调用具体的持久化存储对象(NSPersistentStore
)来操做对应的数据库文件,NSPersistentStore
负责存储的实现细节。这样就很好的将两部分实现了分离。
对于CoreData
的总体结构,由于CoreData
底层存储原本就是用SQLite
实现的,因此我用CoreData
的结构和SQLite
对比了一下,发现仍是不少类似之处的。
.xcdatamodeld
文件表明着数据库文件结构,经过.xcdatamodeld
编译后的.momd
文件生成数据库。每一个实体表明一张数据表,实体之间的关联关系就是SQLite
的外键。
下图就是CoreData
底层存储的结构,用红圈圈住的部分指向关联表的主键下标。例如1
就指向关联表的主键下标为1
的行。
CoreData
本质仍是使用SQLite
进行存储,并无另外提供加密功能,具体的数据加解密还须要本身完成。
CoreData在硬盘上的数据存储结构:
经过PSC
指定建立SQLite
目录后,会在指定的目录下生成一个数据库文件,同时还会生成两个同名但后缀不一样的文件,其中只有后缀.sqlite
的文件是存储数据的文件。
这个数据库文件中会默认生成三个表,Z_METADATA
、Z_PRIMARYKEY
、Z_MODELCACHE
,其余咱们本身的表也都是大写Z开头的。
在每一个表中,系统还会默认生成三个字段,Z_PK
、Z_ENT
、Z_OPT
三个字段,也都是大写Z开头而且带下划线的。其余字段就是咱们本身的字段了,大写Z开头但不带下划线。
如今市面上的大多数项目,都是使用SQLite
做为持久化的方案,而CoreData
的使用并非很广泛。对于这个问题,我认为首先是不少项目开始的比较早,那时候好多iOS
程序员都是从其余语言转过来的,更加熟悉SQLite
,因此用SQLite
比较多一些。后面若是不进行大的项目重构,就很难换其余的持久化方案了。
还有就是不熟悉CoreData
,也不想去了解和深刻学习CoreData
,我认为这是很大的缘由。因此项目中用CoreData
的人并很少,而真正掌握CoreData
技术的人更少。
以前听其余人说CoreData
的执行效率不如SQLite
高,这个若是深究的话,确实CoreData
要比SQLite
效率差一些,只不过并无太大区别。CoreData
本质也是在底层执行SQL
语句,只是CoreData
的SQL
语句执行逻辑比较耗时,没有手动编写SQL
语句更加直接。咱们能够将CoreData
的调试功能打开,具体看一下SQL
语句的执行。
这里要说一点,客户端毕竟不是服务端,不须要像服务器那样大量的数据查询,因此CoreData
是彻底能够应对客户端的查询量的。若是从灵活性来讲,CoreData
确实没有SQLite
的灵活性高,一些SQLite
的复杂功能可能也不能实现,可是就目前大多数项目来讲,CoreData
已经可以知足项目持久化需求了。
致使执行效率差别的缘由还体如今对象转换上,CoreData
在执行SQL
语句的基础上,还多了一层将数据映射给托管对象的操做,这样获得的就是OC
的托管对象,而SQLite
获得的则不是。若是给SQLite
执行完成后,也加一层建立托管对象并赋值的操做,这时候对比性能二者的差距可能就会更小了。
下面是一篇关于CoreData
、FMDB
、Realm
性能测试结果的博客,最后的结果我也没有去验证,只是大体看了一下代码仍是比价靠谱的。做者测试Demo和原文地址。
** 测试数据的数量是以K为单位,最少为1K的数据量。涉及到的操做主要是下面四种**:
1K
条数据。1K
条数据。10K
条数据,连续查询单次为1K
数据。10K
条数据总量,更新其中1K
条数据的部分字段性能。根据测试结果能够发现,在前面两种插入操做,CoreData
的性能比FMDB
和Realm
要快不少。
而对于查询操做,CoreData
比其余两种操做耗时多不少,大概多出三四倍。这极可能和CoreData
将查询结果的数据转为托管对象有关系,抛去CoreData
这部分转换操做性能会比如今好不少。
而更新操做则直接基于SQLite
封装的FMDB
有绝对的优点,FMDB
和其余两种操做差距大概是十倍左右,而其余两种操做性能差很少。固然CoreData
也存在着上面提到的对象转换操做,CoreData
抛去这步结果可能会比如今好不少。
下面的测试数据中,取得是三次测试结果的平均值。
第三方 | 编号 |
---|---|
CoreData | 1 |
FMDB | 2 |
Realm | 3 |
CoreData
本质上是对SQLite
的一个封装,在内部将对象的持久化转化为SQL
语句执行,能够在项目中将CoreData
调试打开,从而能够看到CoreData
的SQL
语句执行和一些其余log
信息。
Product
,选择Edit Scheme
.Arguments
,在下面的ArgumentsPassed On Launch
中添加下面两个选项。 (1)-com.apple.CoreData.SQLDebug
(2)1
若是是在模拟器上调试程序,能够经过 sqlite3 /数据库路径/
命令来查看和操做数据库。 .tables
查看当前数据库文件中全部的表名 select *from tableName
执行查询的SQL
语句
好多同窗都问我有Demo
没有,其实文章中贴出的代码组合起来就是个Demo
。后来想了想,仍是给本系列文章配了一个简单的Demo
,方便你们运行调试,后续会给全部博客的文章都加上Demo
。
Demo
只是来辅助读者更好的理解文章中的内容,应该博客结合Demo
一块儿学习,只看Demo
仍是不能理解更深层的原理。Demo
中几乎每一行代码都会有注释,各位能够打断点跟着Demo
执行流程走一遍,看看各个阶段变量的值。
Demo地址:刘小壮的Github
这两天更新了一下文章,将CoreData
系列的六篇文章整合在一块儿,作了一个PDF
版的《CoreData Book》,放在我Github上了。PDF
上有文章目录,方便阅读。
若是你以为不错,请把PDF帮忙转到其余群里,或者你的朋友,让更多的人了解CoreData,衷心感谢!