一、简单介绍
Core Data是iOS5之后才出现的一个框架,它提供了对象-关系映射(ORM)的功能,即能够将OC对象转化成数据,保存在SQLite数据库文件中,也能够将保存在数据库中的数据还原成OC对象。在此数据操作期间,我们不需要编写任何SQL语句。
对象-关系映射(ORM)
左边是关系模型,即数据库,数据库里面有张person表,person表里面有id、name、age三个字段,而且有2条记录;
右边是对象模型,可以看到,有2个OC对象;
利用Core Data框架,我们就可以轻松地将数据库里面的2条记录转换成2个OC对象,也可以轻松地将2个OC对象保存到数据库中,变成2条表记录,而且不用写一条SQL语句。
二、创建模型
上文已经介绍过,CoreData可以将一个OC对象转化成**关系模型 **(一个表格)存储在SQLite中。那么,现在我们就需要创建一个存储数据的Model类。具体操作如下:
1.创建后缀为.xcdatamodeld的模型文件
command+n:出现如下窗口,点击next
弹出一个窗口,“Save as:”后面修改文件名,点击Creat,出现如下界面:
点击“Add Entity”添加实体,出现绿色框中的“Entity”,双击“Entity”,可以更改实体的名字。比如,改为“People”。机智的骚年,你是不是想到了什么?是的,其实Entity就是一个NSObject。既然如此,我们就可以往这个叫做“Peolpe”的Entity中添加一些属性。点击Attributes下的“+”,如下图:
有时由于项目需求,需要在Entity(例如“People”)中添加另一个Entity(例如“Car”)作为它的属性,而Car也有一个“People”属性。那么,这两个Entity是相互关联的。我们需要给它们添加关联:
第一步:创建一个名为“Car”的Entity。既然是添加关联,我们当然要在Relationships下操作了。点击Relationships下的“+”添加需要关联的Entity( "People" )。“Relationships”:自己定义(所要添加的属性名); “Destination”:要关联的Entity("People") ; “Inverse”:这个暂时不用管它(这个时候还无法操作)。
第二步:既然是相互关联,我们当然也要在People的Relationships下添加一个关联。与第一步类似:“Relationships”:自己定义(所要添加的属性名); “Destination”:要关联的Entity("Car") ; “Inverse”:点击会有一个选择框,我这里的选项是“ower”,选择它。
2.创建NSManagedObject子类
模型文件创建好后,接下来就要根据这个模型文件创建处相应的Model类,具体操作如下:点击 .xcdatamodeld文件--->Editor--->Creat NSManagedObject Subclass
弹出一个窗口,打上勾,点击Creat,又弹出一个窗口,全钩上,Creat。最后,生成八个文件,如下图
三、数据操作
前文已经提过因为CoreData是苹果公司封装的数据持久化框架,所以CoreData数据持久化的操作,不需要编写SQLite语句,而是要用到一些相关的类。比如:NSManagedObjectModel、NSPersistentStoreCoordinator、NSManagedObjectContext等等。
1.CoreData构成的类介绍
(1)NSManagedObjectContext: 被管理者对象上下文, 相当于一个临时数据库, 我们存储或者查询都是通过这个对象来的;
(2)NSManagedObjectModel: 被管理对象模型,可以简单的理解为可视化建模文件(.xcdatamodeld文件), 我们在可视化建模中是Entity自动生成model 方便让文件存储助理来进行管理;
(3)NSPersistentStoreCoordinator: 文件存储助理,相当于数据库的链接器,它是CoreData的核心 负责链接所有的模块, 包括真实的存储文件;
(4)NSManagedObject: 被管理的数据记录,相当于数据库中的表格记录;
(5)NSFetchRequest: 获取数据的请求,相当于SQL语句;
(6)NSEntityDescription: 实体结构,相当于表结构;
2.CoreData核心类初始化
CoreData核心类就是NSManagedObjectModel、NSPersistentStoreCoordinator、NSManagedObjectContext。CoreData的一系列操作都离不开这三个类,也正是因为它们这么重要,所以我们在创建工程时只要勾上CoreData选项,Xcode就会在AppDelegate.m文件中自动生成这三个类的初始化代码。
这些代码你可以写不出来,但是一定要清楚它们的作用,下面将对这些代码做一些介绍注释:
//获取沙盒Document目录路径
- (NSURL*)applicationDocumentsDirectory {
return[[[NSFileManager defaultManager]URLsForDirectory:NSDocumentDirectoryinDomains:NSUserDomainMask]lastObject];
}
//被管理的对象模型
- (NSManagedObjectModel*)managedObjectModel {
if(_managedObjectModel!=nil) {
return_managedObjectModel;
}
//这里的@"*Model*"需要与.xcdatamodeld文件的名字一样;.xcdatamodeld编译后为.momd或.mom文件
NSURL*modelURL = [[NSBundle mainBundle]URLForResource:@"*Model*"withExtension:@"momd"];
_managedObjectModel= [[NSManagedObjectModel alloc]initWithContentsOfURL:modelURL];
return_managedObjectModel;
}
//持久化存储助理:相当于数据库的连接器
- (NSPersistentStoreCoordinator*)persistentStoreCoordinator {
if(_persistentStoreCoordinator!=nil) {
return_persistentStoreCoordinator;
}
_persistentStoreCoordinator= [[NSPersistentStoreCoordinator alloc]initWithManagedObjectModel:[self managedObjectModel]];
//CoreData是建立在SQLite之上的,数据库名称需与.cdatamodel文件同名
NSURL*storeURL = [[self applicationDocumentsDirectory]URLByAppendingPathComponent:@"Model.sqlite"];
NSError*error =nil;
NSString*failureReason =@"There was an error creating or loading the application's saved data.";
if(! [_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
NSMutableDictionary*dict = [NSMutableDictionary dictionary];
dict[NSLocalizedDescriptionKey] =@"Failed to initialize the application's saved data";
dict[NSLocalizedFailureReasonErrorKey] = failureReason;
dict[NSUnderlyingErrorKey] = error;
error = [NSError errorWithDomain:@"YOUR_ERROR_DOMAIN"code:9999userInfo:dict];
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
return_persistentStoreCoordinator;
}
//被管理的上下文:操作实际内容
- (NSManagedObjectContext*)managedObjectContext {
if(_managedObjectContext!=nil) {
return_managedObjectContext;
}
NSPersistentStoreCoordinator*coordinator = [self persistentStoreCoordinator];
if(!coordinator) {
return nil;
}
_managedObjectContext= [[NSManagedObjectContext alloc]initWithConcurrencyType:NSMainQueueConcurrencyType];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
return_managedObjectContext;
}
//保存数据
- (void)saveContext {
NSManagedObjectContext*managedObjectContext =self.managedObjectContext;
if(managedObjectContext !=nil) {
NSError*error =nil;
if([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
}
}
3.增、删、改、查操作
以下操作均是利用Xcode自动在AppDelegate初始化CoreData的核心对象,所以首先需要初始化一个AppDelegate对象
AppDelegate*app=[[AppDelegate alloc]init];
插入数据
NSManagedObject*object=[NSEntityDescription insertNewObjectForEntityForName:entity inManagedObjectContext:app.managedObjectContext];
//第一种方式
[object setValue:@"Kevin" forKey:@"name"];
//第二种方式
(People*)people=object;
object.name=@"Kevin";
.......
//插入操作结束后记得保存
[app saveContext];
删除数据
[app.managedObjectContext deleteObject:object];
[app saveContext];
查询数据
//创建取回数据请求
NSFetchRequest*request=[[NSFetchRequest alloc]init];
//设置检索的实体描述
NSEntityDescription*entityDes=[NSEntityDescription entityForName:@"People" inManagedObjectContext:app.managedObjectContext];
[request setEntity:entityDes];
//指定对检索结果的排序方式(根据People的name属性,按升序排列)
NSSortDescriptor*sortDestor=[[NSSortDescriptor alloc]initWithKey:@"name" ascending:YES];
[request setSortDescriptors:@[sortDestor]];
//创建谓词(搜索name=@"Kevin"的数据)
NSPredicate*predicate=[NSPredicate predicateWithFormat:@"name=%@",@"Kevin"];
request.predicate=predicate;
NSError*error=nil;
//执行请求,返回数组
NSArray*fetchedResult=[app.managedObjectContext executeFetchRequest:request error:&error];
修改数据
修改数据其实就是将查询操作时返回的数组中的元素取出,直接修改。(数组中的元素是指向内存地址的指针)
(People*)people=fetchedResult[0];
people.name=@"Tom";
项目开发过程中,在AppDelegate中初始化CoreData的核心对象并不是一种提倡的做法。我们通常的做法是封装一个CoreDataManager的单例类。篇幅有限,这个将在下一章中介绍。
网友评论