使用Core Data 框架
Core Data框架本质就是一个ORM(对象关系映射(英语:Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序技术,
用于实现面向对象编程语言里不同类型系统的数据之间的转换。)虽然Core Data
也允许把数据保存在内存中,或存储为非SQLite数据库的其他存储格式,但实际上绝大部分情况下,Core Data底层都采用SQLite数据库作为持久存储方式
Core Data简介
Core Data是一个纯粹的面向对象框架,可用于管理实体以及实体之间的关联关系的持久化—Core Data可以将实体保存到持久存储设备中,也可以在需要的时候将它们取出来. |
Core Data底层的持久化存储方式可以是SQLite数据库,也可以是XML文档,甚至可以直接以内存作为持久化存储设备(选择内存作为持久化存储设备,应用重启时,数据就会丢失.) |
Core Data的核心概念是实体.实体是由Core Data管理(简称被托管)的模型对象,它必须是NSManagedObject类或其子类的实例.实体与实体之间存在1-11-NN-N的关联关系,整个应用的所有实体以及实体之间的关联关系被称为托管对象模型(NSManagedObjectModel). |
Core Data的核心对象是托管对象上下文(NSManagedObjectContext,有时也简称上下文),所有实体都处于托管对象上下文管理中,Core Data应用对实体所做的任何增删改查操作必须通过托管对象上下文来完成. NSManagedObjectContext底层与持久化存储协调器衔接,持久化存储协调器则负责管理底层的存储形式(比如SQLite). |
Core Data应用中的核心API有如下几个.
托管对象模型(NSManagedObjectModel): |
该对象负责管理整个应用的所有实体以及实体之间的关联关系.当开发者使用Xcode的图形界面设计了实体与实体的关联关系之后,需要使用该对象来加载,管理应用的托管对象模型. |
持久化存储协调器(NSPersistentStoreCoordinator): |
负责管理底层的存储文件,例如SQLite数据库等. |
托管对象上下文(NSManagedObjectContext): |
该对象是Core Data的核心对象,应用程序对实体所做的增删改查操作都需要通过该对象来完成. |
实体描述(NSEntityDescription): |
该对象代表了关于某个实体的描述信息,从某种程度来说,该对象相当于实体的抽象. 实体描述定义了该实体的名字实体的实现类,并用一个集合定义了该实体包含的所有属性 |
抓取请求(NSFetchRequest) |
该对象封装了查询实体的请求,包括程序需要查询哪些实体查询条件排序规则等 |
掌握了API之后,使用Core Data持久化操作的步骤大致如下.
1 |
创建NSManagedObjectModel对象来加载管理应用的托管对象模型 |
2 |
以NSManagedObjectModel对象为基础,根据实际需要创建NSPersistentStoreCoordinator对象,该对象确定Core Data底层数据的存储形式 |
3 |
以NSManagedObjectModel对象为基础,创建NSManagedObjectContext,该对象是Core Data进行持久化访问的核心对象 |
4 |
对于普通的增删改操作,需要分别先新建实体删除实体修改实体,然后调用NSManagedObjectContext对象的save:方法将这些修改保存到底层存储设备 |
5 |
如果要执行查询,则需要先创建NSFetchRequest对象,再调用NSManagedObjectContext的executeFetchRequest: error:方法执行查询,该方法返回所有匹配条件的实体组成的NSArray. |
初始化Core Data项目
iOS允许在创建iOS项目时勾选”Use Core Data”复选框,通过这种方式创建的iOS项目已经完成了所有Core Data必需资源的初始化.
“手动”初始化Core Data项目步骤如下
1 |
为该项目添加CoreData.framework框架.为了让项目显示更好的组织结构,将该框架拖入项目的Frameworks目录下 |
2 |
为该项目添加一个实体模型文件,单击Xcode主菜单的”File” →”New”→”File”菜单项,Xcode显示下图所示的对话框 |
3 |
初始化Core Data应用必需的核心API对象:NSManagedObjectModelNSPersistentStoreCoordinatorNSManagedObjectContext. |
4 |
在AppDelegate.m文件中-(void)applicationWillTerminate:(UIApplication *)application方法---当应用将要被中断时,应用程序会自动回调 该方法,该方法中调用saveContext方法执行保存.如果不在该方法中执行保存,当应用被中断后,该应用可能进入后台,就有可能在后台被终止,这样就会导致该托管对象上下文中保存的数据丢失. |
设计实体模型
对模型可以添加如下3种对象 |
||
实体 |
这是实体模型最核心的对象,每个实体都必须是NSManagedObject类或其子类 |
|
抓取请求 |
NSFetchRequest对象,Xcode允许在图形界面上设计抓取请求对象,但实际上,通常都会在代码中创建NSFetchRequest对象 |
|
配置 |
一般无须自行添加配置对象,当开发者添加实体后,系统会自动添加默认的配置 |
|
每个实体可以添加如下的3种属性 |
||
属性(Attribute) |
该属性相当于实体对象的实例变量,用于记录该实体的状态. |
|
关联关系(Relationships) |
该属性定义实体之间的1:11:NN:N关联关系. |
|
抓取属性(Fetched Properties) |
这是关联关系的可选方法,抓取属性允许在获联关联实体时执行某个过滤条件. |
添加一个简单的实体
- 单击上图所示界面左下角的“Add Entity”按钮,系统将会在ENTITIES列表下添加一个实体,将该实体重命名为项目所需的名字,
- 此处重名为LCEvent。提示:“长按“Add Entity”按钮,该按钮将会显示Add Entity、Add Fetch Request、Add Configuration列表,
- 可以选择其中一项来添加实体、抓取请求、配置。”
- 选中LCEntity实体,通过单击上图所示界面右下角的“Add Attribute”按钮,系统将会为该LCEntity实体添加一个属性,
- 将该属性重名为项目所需的名字,此处重命名为name,并为该属性选择类型,此处选择String类型。
重复第2步,为该实体再次添加happenDate属性,并将该属性设置为Date类型。
实体设计完成后,将可以看到下图所示的效果
- 单击Xcode主菜单的”Editor” →”Create NSManagedObject Subclass”菜单项,如果系统包含两个以上实体,Xcode将会弹出一个
- 对话框让我们选择要为那些实体生成NSManagedObject的子类,然后弹出对话框让我们选择NSManagedObject的子类测存储路径.
该实体包含两个属性,但不包含任何关联关系.
使用Core Data实现数据的增、删、改、查
添加实体
1 |
调用NSEntityDescription的insertNewObjectForEntityForName:inManagedObjectContext:静态方法添加新实体.该方法的第1个参数为实体名,第2个参数为NSManagedObjectContext对象 |
2 |
为新实体设置属性 |
3 |
调用NSManagedObjectContext对象的save:方法执行保存. |
代码片段 |
1 //控制Core Data在托管对象上下文中创建一个新实体 2 3 LCEvent *event = [NSEntityDescription insertNewObjectForEntityForName:@”LCEvent” 4 5 inManagedObjectContext:self.appDelegate.managedObjectContext]; 6 7 //为新实体设置属性 8 9 . . . 10 11 //定义一个NSError对象,用于接收错误信息 12 13 NSError *error; 14 15 //设置完实体属性之后,调用托管对象上下文的save:方法将实体写入数据库.如果保存成功 16 17 if ([self.appDelegate.managedObjectContext save:&error]) 18 19 { 20 21 . . . 22 23 } 24 25 else 26 27 { 28 29 NSLog(@”保存实体出错: %@,%@”,error, [error userInfo]); 30 31 } |
删除实体
删除实体的步骤如下
1 |
获取要删除的实体 |
2 |
调用NSManagedObjectContext对象的deleteObject:方法删除实体. |
3 |
调用NSManagedObjectContext对象的save:方法执行保存. |
代码片段 |
//获取将要删除的实体 LCEvent *deleteEvent = . . .; //从托管对象上下文中删除指定对象 [self.appDelegate.managedObjectContext deleteObject:deleteEvent]; // 定义一个NSError对象,用于接收错误信息 NSError *error; // 保存删除操作,如果出现错误,则显示错误信息 if(![self.appDelegate.managedObjectContext save:&error]) { NSLog(@”删除实体出错: %@,%@”,error,[error userInfo]); } |
修改实体
修改实体的步骤如下
1 |
获取要修改的实体(必须是处于NSManagedObjectContext管理下的实体) |
2 |
修改实体的属性. |
3 |
调用NSManagedObjectContext对象的save:方法执行保存. |
代码片段 |
//获取将要修改的实体 LCEvent *updateEvent = . . .; //从托管对象上下文中删除指定对象 . . . // 定义一个NSError对象,用于接收错误信息 NSError *error; // 保存删除操作,如果出现错误,则显示错误信息 if(![self.appDelegate.managedObjectContext save:&error]) { NSLog(@”删除实体出错: %@,%@”,error,[error userInfo]); } |
查询实体
查询实体的步骤如下.
1 |
创建NSFetchRequest对象 |
|
2 |
通过NSEntityDescription对象设置NSFetchRequest对象将要抓取的实体 |
|
3 |
如果需要对抓取结果进行筛选,则需要通过NSPredicate(谓词)对象设置筛选条件.如果需要对结果进行排序,还需要为NSFetchRequest添加多个NSSortDescription对象 |
|
4 |
调用NSManagedObjectContext对象的executeFetchRequest:error:方法执行查询,该查询方法将会返回所有符合条件的实体组成的NSArray集合 |
|
代码片段 |
// 创建抓取数据的请求对象 NSFetchRequest *request = [[NSFetchRequest alloc] init]; // 设置要抓取哪种类型的实体 NSEntityDescription *entity = [NSEntityDescription entityForName:@”LCEvent” inManagedObjectContext:self.appDelegate.managedObjectContext]; // 设置抓取实体 [request setEntity:entity]; // 定义抓取条件 request.predicate = [NSPredicate predicateWithFormat:. . .]; NSError *error = nil; // 执行抓取数据的请求,返回符合条件的数据 NSArray *array = [[self.appDelegate.managedObjectContext executeFetchRequest:request error:&error] mutableCopy]; |
管理实体的关联关系
Core Data除了可用于管理单独的实体之外,还可以用于管理实体与实体之间的关联关系.新建一个项目,并通过勾选”Use Core Data”选项来初始化
Core Data应用----通过这种方式创建的项目,Xcode已经为项目做好了如下准备工作
- 添加了CoreData.framework框架.
- 添加了一个空的.xcdatamodeld实体设计文件.
- 在应用程序委托类中为Core Data的3个API定义了属性,并提供了方法执行初始化.
- 重写了应用委托类的- (void)applicationwillTerminate:(UIApplication *)application方法,并在该方法中调用了托管对象上下文的save:方法执行保存.