了解SQLite的使用,我们知道SQLite是一个关系型数据库,需要使用SQL语言来进行操作,而SQLite需要通过C调用对应的API,并进行一些底层的封装操作,而且Model对象文件需要自己编写,代码量会非常多。
所以苹果在2005年第一次引入了Core Data框架,与SQLite相比,Core Data避免了SQL的复杂性,能让开发者更自然地与数据库进行交互。
Core Data简介
Core Data是伴随着iOS 5 出现的一个框架,它位于SQLite数据库之上,可以将模型对象保存到持久化存储中,并在需要的时候将他们取出。
由于Core Data位于MVC设计模式的Model层,他能将应用程序中的对象直接保存到数据库中,无需进行复杂查询,也无需确保对象的属性名和数据库字段名相对应,因此,与SQLite相比,使用Core Data为Model层编写的代码行数会减少为原来的50%至70%。
在Core Data框架中包含了几种类型的对象,这些对象的集合用术语叫做堆栈(Stock),下面是苹果官方描述Core Data框架堆栈的图片:
由图中可以看出,Core Data框架中的堆栈包含4个模块,他们分别的作用如下:
- Managed Object Model(托管对象模型):描述应用程序的数据模型,也就是数据库中数据表记录的对象表示,由Core Data管理的模型(Model)对象。
- Managed Object Context(托管对象上下文):参与数据库进行各种操作的全过程,并监测数据对象的变化,在上下文中可以查找,删除和插入对象。
- Persisent Store Coordinator(持久化存储协调器):相当于数据文件管理器,处理底层的对数据文件的读取和写入。通常情况下,它是数据库与对象之间的桥梁,专门用来添加持久化存储数据库(如SQLite数据库),一般开发者无需与它打交道。
- Persistent Object Store(持久化对象存储库):用来存储对象模型。从概念上讲,一个持久化存储(Persistent Store)就像一个数据库,有数据表和数据记录。
Core Data提供了对象-关系映射(ORM)的功能,即能够将OC对象转为数据,保存在SQLite数据库文件中, 也能够将保存在数据库中的数据还原成OC对象,比如下图所示:
由图中可以看出,关系模型(即数据库)中包含person表,person表中有id,name,age等3个字段,而且包含了两条记录;对象模型则包含的是2个OC对象,我们可以通过Core Data框架,轻松将数据库中的2条记录转换为2个OC对象,也可以轻松地将2个OC对象保存到数据库中,变成2条表记录。
需要注意的是,使用Core Data实现关系模型和对象模型的转换过程是不需要编写任何SQL语句的。
Core Data使用
没用过,书上看的,先记下来吧,感觉这东西挺烦的:
使用coreData的好处之一就是可以减少Model层代码的编写,但是要使用CoreData,首先需要学会创建模型实体,为了方便,我们可以在Xcode工具中创建模型实体:
在Xcode工具中创建模型实体
新建项目
注意新建项目时要勾选“Use Core Data”。当创建项目时勾选“Use
Core Data”,创建的iOS项目已经完成了Core Data所有重要资源的初始化,包括为项目添加的Core Data.framework框架。
创建模型实体
1,项目中”command + N”,选择iOS→”Core Data”→”Data Model”,然后新建Model文件即可;
2,到Model文件中,点击”Add Entity”,按钮可以添加实体,修改实体名,。
注意:”Add Entity” 按钮长按会显示“Add Entity”、“Add Fetch Request”和“Add Configuration”三个选项,我们可以选择其中一项来进行添加实体、添加抓取请求,添加配置等。
“Add Attribute”按钮长按,会显示“Add Attribute”、“Add Relationship”和“Add Fetched Property”列表,我们可以选择其中一项来添加属性、添加关联关系、添加抓取属性等。
添加模型实体的基本属性
点击“Add Attribute”为模型添加属性。
为模型生成实体关联类
“command + N”→”iOS “→”Core Data”→”NSManagerObject subclass”,然后next之后,进入选择实体类所关联的模板最后再继续,再确定。
然后会发现项目中多了Model类文件 。
使用Core Data插入、查询、删除数据
下面分步骤讲解如何使用Core Data对数据进行添加、查询、删除等操作:
打开数据库
- (void)openDB{
//1,从应用程序包中加载模型文件
NSManagedObjectModel *model = [NSManagedObjectModel mergedModelFromBundles:nil];
//2,传入模型对象,初始化NSPersistentStoreCoordinator
NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] init];
//3,构建SQLite数据库文件的路径
NSString *docs = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSLog(@"%@",[docs stringByAppendingPathComponent:@"person.db"]);
NSURL *url = [NSURL fileURLWithPath:[docs stringByAppendingPathComponent:@"person.db"]];
//4,添加持久化存储库,这里使用SQLite作为存储库
NSError *error = nil;
NSPersistentStore *store = [psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:url option:nil error:&error];
if (store == nil) {//直接抛异常
[NSException raise:@"添加数据库错误" format:@"%@",[error localizedDescription]];
}else{
NSLog(@"添加数据库成功");
}
//5,初始化上下文,设置persistentStoreCoordinator属性
//@property (nonatomic, strong, readonly) NSManagedObjectContext *sharedContext;//做好属性声明
_sharedContext = [[NSManagedObjectContext alloc] init];
_sharedContext.persistentStoreCoordinator = psc;
}
为模型插入数据
当为模型插入数据时,首先需要通过传入上下文,创建实体对象,然后设置实体的属性,然后调用NSManagedObjectContext对象的save方法执行保存:
- (IBAction)insertData:(id)sender{
//传入上下文,创建Person实体对象
NSManagedObject *person = [NSEntityDescription insertNewObjectForEntityName:@"Person" inManagedObjectContext:_sharedContext];
//设置Person的简单属性
NSString *nameStr = [NSString stringWithFormat:@"itcast-%d",arc4random_uniform(100)];
[person setValue:nameStr forKey:@"name"];
int age = 10 + arc4random_uniform(40);
[person setValue:[NSNumber numberWithInt:age] forKey:@"age"];
//让上下文进行保存
NSError *error = nil;
BOOL success = [_sharedContext save:&error];
if (!success) {
[NSException raise:@"访问数据库错误" format:@"%@", [error localizedDescription]];
}else{
NSLog(@"添加数据成功");
}
}
查询数据
若要查询,需要先创建NSFetchRequest对象,再调用NSManagedObjectContext的executeFetchRequest:error方法进行查询,该方法会返回所有匹配条件的实体组成的NSArray。若需要对查询结果进行筛选,这需要通过NSPredicate设置筛选条件;若需要对筛选结果排序,还需要为NSFetchRequest添加多个NSSortDescription对象:
- (IBAction)selectData:(id)sender{
//初始化一个查询请求
NSFetchRequest *request = [[NSFetchRequest alloc] init];
//设置要查询的实体
request.entity = [NSEntityDescription entityForName:@"Person" inManagedObectContext:_sharedContext];
//设置排序(按照age降序)
NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:NO];
request.sortDescriptors = [NSArray arrayWithObject:sort];
//设置条件过滤
request.predicate = [NSPredicate predicateWithFormat:@"name like %@", @"*itcast-4*"];
NSError *error = nil;
NSArray *objs = [_sharedContext executeFetchRequest:request error:&error];
self.toBeDeleted = objs;
//返回操作结果信息
if (error) {
[NSException raise:@"查询错误" format:@"%@", [error localizedDescription]];
}else{
NSLog(@"查询成功");
}
//遍历数据
for (NSManagedObject *obj in obj) {
NSLog(@"name = %@",[obj valueForKey:@"name"]);
}
}
注意设置条件过滤时,数据库SQL语句中的%要用代替,所以%itcast-4%应该写成 *itcast-4*
删除数据
删除数据方式比较简单,只需要获取要删除的实体,调用NSMan对象的deleteObject方法删除,最后调用NSManagedObjectContext对象的save方法保存即可。
- (IBAction)deleteData:(id)sender{
for(NSManagedObject * obj in self.toBeDeleted) {
[_sharedContext deleteObject:obj];
}
//将结果同步到数据库
NSError *error = nil;
//让上下文进行保存
[_sharedContext save:&error];
//返回操作结果信息
if (error) {
[NSException raise:@"删除错误" format:@"%@", [error localizedDescription]];
}else{
NSLog(@"删除成功");
}
}
注意,若要想删除实体,必须首先查询实体,并且按照条件查询来获取删除的实体。