CoreData 框架简介(一)

CoreData 框架简介(一)

这是该系列文章的第一篇,总体上介绍一下CoreData,目的是让我们对其概念和使用有个初步的印象和了解,由于大部分都是文字内容,看起来可能会比较枯燥,但是还是建议大家努力看完。


iOS3.0引入的CoreData,用于本地存储和检索持久化数据;CoreData是一个功能强大的对象数据库,提供了强大的数据存储和管理能力。

CoreData能将对象映射到关系数据库,让你在编写对象业务逻辑时,无需创建数据库,也不用编写持久化逻辑,专注于应用需求;

下面是CoreData提供的一些主要功能:

1)使用可视化模型编辑器进行数据对象建模;

2)处理对象架构(schema)变更的自动和手动迁移工具;

3)在对象之间建立一对一、一对多和多对多关系;

4)以不同的格式将数据存储到独立的文件中;

5)对象特性(attribute)验证;

6)数据查询和排序;

7)延迟加载数据;

8)与iOS表视图紧密协作;

9)使用提交和撤销功能管理相关对象的变更;


看起来可能有些不太好理解,但是当您对比数据库的使用时,这些优点就会显现;

1 判断是否适合使用CoreData

iOS中的数据持久化方式有很多中:

1)NSUserDefault:

这种方式通常用于保存应用的首选项;

很像使用键值存储的NSDictionary,可存储NSNumber,NSString,NSDate,NSData,NSDictionary,NSArray表示的值,还可存储任何遵守了NSCoding协议的对象,如果使用键值对,字典或数组可以满足应用的持久化需求,就可以使用NSUserDefault。

2)属性列表(plist):

NSDictionary和NSArray都支持读写用户定义的属性列表文件,这种方式采用xml格式,可存储NSNumber,NSString,NSDate,NSData,NSDictionary和NSArray;如果使用字典或数组可满足应用的持久化需求,就可以使用属性列表文件。

3)编码器(Coder)和键式归档(Keyed Archive):

NSCoder和NSKeyedArchiver支持将任何对象存储到二进制文件中;要使用这种持久化方式,要存储的每个自定义对象必须实现NSCoder定义的方法,而开发人员必须负责保存和加载;如果只需要几个自定义对象就能满足应用的持久化需求,就可以使用这种方式。

4)直接使用SQLite:

应用可以使用C语言库libsqlite直接与SQLite数据库交互;SQLite是一种嵌入式关系数据库,不需要服务器,支持SQL92描述的大部分标准SQL语言;在iOS应用中,使用SQLite可实现SQL支持的任何数据持久化逻辑,如定义数据库表和关系,插入数据,查询数据以及更新和删除数据;这种方式的缺点是,应用需要在对象和SQL文件之间建立映射,需要编写检索和保存数据的SQL查询,还需编写代码来跟踪保存的对象。

5)CoreData:

提供了直接使用SQLite的大部分灵活性,同时应用无需关系数据库使用机制;如果应用需要的数据很多,需要维护对象之间的关系或需要快速而轻松的访问特定对象,CoreData可能是不错的选择。


使用CoreData时,应用中通常需要用到的类:

托管对象(Managed object)是NSManagedObject实例,用于存储数据;

托管对象上下文(NSManagedObjectContext)是一个工作区,应用用它来创建、查询和保存托管对象;


2 CoreData托管对象

描述下CoreData的托管对象:

托管对象是什么;

如何在对象模型中定义它们;

应用如何与托管对象交互;

以及在托管对象的定义发生变化时如何应对;


2.1 托管对象

托管对象是NSManagedObject实例,应用主要与之交互;可将托管对象视为字典,包含一组已知的键和对象类型(如字符串或数组),类似这样:

NSString * movieName = [myMovie valueForKey:@"movieName"];

要更新特性,可使用setValue:forKey。

[myMovie setValue:@"Casablanca" forKey:@"movieName"];

可将托管对象定义为NSManagedObject的子类,这样就可以像访问属性那样访问特性;

NSManagedObject子类可以包含自定义方法,多用于功能性的辅助;

可在托管对象之间建立关系,比如在跟踪电影收藏中,被跟踪的电影是否借给了朋友可能有用,为此,可创建Movie和Friend,并建立二者之间关系;

可以是一对一,也可是一对多(比如一个人借了多部电影):

[myMovie setValue:myFriend forKey:@"lentToFriend"];
[myOtherMovie setValue:myFriend forKey:@"lentToFriend"];
NSSet * borrowedMovies = [myFriend valueForKey:@"borrowedMovies"]

这是一对多的例子,将多部电影借给某人,实际上是为关系(lentToFriend和borrwoedMovies是Inverse关系)对应的属性(Friend和NSSet)赋值和取值的过程;


2.2 托管对象模型

托管对象模型(NSManagerdObjectModel)中定义的;托管对象模型包含了一系列实体,实体的特性,特性和实体的有效性约束以及实体之间的关系;

托管对象模型通常是使用Xcode可视化模型编辑器创建的;如果创建项目时选择use coredata,会自动创建一个xxx.xcdatamodeld的文件,也可以手动创建,这个就是可视化模型编辑器;


上图中显示了Movie(实体)的特性以及相应的数据类型;

CoreData支持数据类型如下:

数据类型对应的OC数据类型
Integer 16NSNumber
Integer 32NSNumber
Integer 64NSNumber
DecimalNSNumber
DoubleNSNumber
FloatNSNumber
StringNSString
BooleanNSNumber
DateNSDate
Binary DataNSData
Transformable使用值转换器(NSValueTransformer)

CoreData支持实体继承(上图中Parent Entity),对于任何实体,都可以指定一个父实体,子实体将继承父实体的所有特征,包括特性、有效性约束和索引。

2.3 托管对象迁移

如果需要修改对象模型(即便给实体添加一个特性,也被视为修改了对象模型),就需要对模型进行版本控制;

加载既有的持久存储区时(稍后我会给出一张图,方便大家理解啥时持久存储区),CoreData将对其进行检查,确保他与对象模型匹配,如果不匹配,就需要根据新的对象模型将持久存储区的数据迁移到新的持久存储区;

CoreData能够根据持久存储协调器(稍后看图)中设置的选项自动处理众多的简单迁移,如果需要额外的逻辑,可能还要编写迁移;

这块内容比较复杂,在实践之后,我会在后续的blog中单独写一篇文章来学习。

2.4 创建托管对象

托管对象只能存在于托管对象上下文(NSManagedObjectContext)中,而托管对象上下文是CoreData的工作区;托管对象要么是在托管对象上下文中创建的,要么是从托管对象上下文获取的;要创建托管对象,需要一个指向托管对象上下文的引用;然后需要指定托管对象的实体,在CoreData框架中,又一个NSEntityDescription的类,提供了有关实体的信息(可使用其类方法创建);

NSManagedObject * moc = kAPPDelegate.managedObjectContext;//应用委托设置了一个用于存储上下文的属性
NSManagedObject * newObject = [NSEntityDescription insertNewObjectForEntityForName:@"MyEntity" inManagedObjectContext:moc];//指定托管对象的实体

有了托管对象,就可以更新其相关特性,设置好之后,需要保存托管对象上下文,以持久化托管对象:

NSError * mocSaveError = nil;
if(![moc save:&mocSaveError]){

}

要撤销不想要的修改,可以回滚托管对象上下文;

if([moc hasChanges]){
    [moc rollback];
}

这里给出一张图,方便大家理解上述几个重要概念的关系:


2.5 对象检索和排序

要使用既有的托管对象,需要从托管对象上下文中取回;检索托管对象的方式有两种:直接使用objectID;编写检索请求;
1 直接使用objectID:
CoreData给每个托管对象都指定了独一无二的ID,这就是一个名为objectID的NSManagedObjectID实例;可以使用已有的objectID取回托管对象:
NSManagedObject * myObject = [kAppDelegate.managedObjectContext objectWithID:myObjectID];

如果没有找到则返回nil;找到了将返回一个NSManagedObject;
2 编写检索请求:
要根据特性检索托管对象,需要使用检索请求(NSFetchRequest实例);检所请求需要知道要检索的是哪种实体,这可使用NSEntityDescription来指定;
NSFetchRequest * fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription * entity = [NSEntityDescription entityForName:@"MyEntity" inManagedObjectContext:moc];
[fetchReuqest setEntify:entity];


检索请求还可能包含可选的排序描述符(NSSortDescriptor),以指定检索结果的排列顺序;
创建排序描述符:指定特征名和排序方向(升序还是降序),将排序描述符加入一个数组,加入顺序对应排序描述符的优先级;
NSSortDescriptor * sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"sortAttributeName" ascending:YES];
NSArray * sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
[fetchRequest setSortDescriptors:sortDescriptors];

检索请求还可以使用谓词(NSPredicate),他指定了检索结果必须满足的条件;谓词在后续使用中会详细介绍,如下是简单示例:
NSPredicate * predicate = [NSPredicate predicateWithFormat:@"attribute == %@",@"value"];
[fetchRequest setPredicate:predicate];

检索请求返回的是一个数组,包含0~多个对象;
对检索请求配置可以返回特性而不是对象,还可以使其返回聚合函数(sum和count)的结果;(这个应该比较常用吧,还不知道该怎么用,回头找找?)


2.6 检索结果控制器

fetch results controller能将检索结果与表视图关联;
检索结果控制器通过配置检索请求,将返回的结果组织成可通过索引路径访问的部分和行;暴露的方法,也为实现表视图所需信息提供了便利;
检索结果控制器还会监听CoreData中的变化,并使用委托更新表视图;

3 CoreData环境

CoreData隐藏了持久化机制,让应用代码能够直接使用模型对象,而不用关心他们是如何存储和保存的;
为此,Core Data利用4个主要的类来定义环境:
NSManagedObjectModel;
NSPersistentStoreCoordinator;
NSPersistentStore;
NSManagedObjectContext;
新项目添加CoreData只需创建托管对象模型,对环境中其他方面进行定制,就可编写使用CoreData的逻辑;
要实例化托管对象模型,可从模型文件加载它;实例化托管模型之后,就可以将它关联到持久存储协调器;

3.1 持久存储协调器
持久存储协调器(NSPersistentStoreCoordinator)是中间人,位于存储对象的实际文件和应用与之交互的对象模型之间;
除了搭建CoreData环境时实例化持久存储协调器外,应用通常不与他做交互;
持久化存储协调器可管理与多个存储区的通信,从而将数据存储的细节隐藏起来;
实例化持久存储协调器后,需要将持久存储区加入其中,这样才能访问数据;

3.2 持久存储区
持久存储区(NSPersistentStore)表示存储数据的文件;配置应用使用CoreData时,只需指定持久存储区的名称,位置和类型;
在iOS中,CoreData可使用的存储区类型包括SQLite和二进制文件(在Mac OS X中,可使用XML);
使用SQLite,可以让CoreData能够利用查询功能改善性能;CoreData直接管理SQLite文件;CoreData不能使用既有的SQLite文件,必须创建文件和架构(schema)(这是CoreData首次使用不存在的文件时完成的);

将持久存储区加入持久存储协调器后,就可以创建托管对象上下文与委托对象交互了;

3.3 托管对象上下文
托管对象上下文(NSManagedObjectContext)是包含托管对象的工作区;创建、删除、查询对象,应用都必须与托管对象上下文交互;他还能管理相关的变更(保存修改或撤销);

同时可以使用多个托管对象上下文,以便将不同的操作分开;
比如:应用需要显示一组数据,同时从web服务导入一些数据,这时,可在主线程中使用一个托管对象上下文来查询和显示,再在后台线程中使用另一个托管对象上下文从web服务导入数据;导入数据之后,可将两个托管对象上下文合并,然后删除后台上下文;
CoreData的功能非常强大,能够处理在两个上下文中修改同一个对象的情形,还能够修改合并;

4 小结

若干概念:包括托管对象,托管对象上下文,可视化托管对象编辑器;
CoreData环境:持久化存储协调器,持久化存储区;
上边给出的关系图,很好的说明了彼此之间的关系,使用的时候先搭建环境,利用可视化托管对象编辑器编辑和生成托管对象model,利用检索结果控制器进行交互;

以上的内容适用于iOS10之前的CoreData,iOS10之后,对CoreData提供了新的API;上述内容偏理论,主要是为了让大家熟悉CoreData,即便没全理解也不用担心,下一节会实践CoreData实际操作托管对象,参照示例再回看这部分内容就容易理解的多。



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值