一、介绍下Core Data
CoreData在早些年iOS开发中使用不多,因为其本身性能略低,以及不使用SQL语句而失去的灵活性,再加上FMDB之类封装SQLite的三方框架很好用,所以一直不受待见。最近越来越多的开发中开始使用CoreData,原因也许是因为如今的设备性能的提升,大家又慢慢的看到了CoreData的优点,比如不用SQL语句(笔者很喜欢这点,哈哈),配置使用的方式也比较简单(刚开始使用时可能感觉有点复杂,用于连接“对象”和“关系”的类好多。。但是模式本身是很简单的,也很容易实现,熟练而已)。
下面开始好好聊聊CoreData吧,看完至少使用它不再是问题~
Core Data是iOS5之后才出现的一个框架,它提供了对象-关系映射(ORM)的功能,即能够将OC对象转化成数据,保存在SQLite数据库文件中,也能够将保存在数据库中的数据还原成OC对象。在此数据操作期间,我们不需要编写任何SQL语句,这个有点类似于著名的Hibernate持久化框架,不过功能肯定是没有Hibernate强大的。
CoreData本质是一个ORM框架 ORM Objective-Relational Mapping 这个映射就是我们的模型文件,一般ORM框架都用XML格式来映射实体Entity+属性数据库表。
托管对象(entity) —既不是单纯的内存对象,也不是数据库中的具体的数据,它介于这两个状态之间的,我们叫他游离态的数据(很蛋疼的说法)。
CoreData不能执行SQL语句,取而代之,操作的是对象, FMDB SQLite可以直接SQL语句,对于很多面向对象的开发者来说,操作对象更为习惯。
给出一张图,看看“关系”和“对象”
- 左边是关系模型,即数据库,数据库里面有张person表,person表里面有id、name、age三个字段,而且有2条记录; 右边是对象模型,可以看到,有2个OC对象; 利用Core Data框架,我们就可以轻松地将数据库里面的2条记录转换成2个OC对象,也可以轻松地将2个OC对象保存到数据库中,变成2条表记录,而且不用写一条SQL语句。
二、coredata中的核心对象
注:黑色表示类名,红色表示类里面的一个属性
1、常规开发步骤(不理解没关系,后面有代码。。):
(1)初始化NSManagedObjectModel对象,加载模型文件,读取app中的所有实体信息
(2)初始化NSPersistentStoreCoordinator对象,添加持久化库(这里采取SQLite数据库)
(3)初始化NSManagedObjectContext对象,拿到这个上下文对象操作实体,进行CRUD(创建(Create)、更新(Update)、读取(Read)和删除(Delete))操作
2、核心对象
(1)CoreData 持久化协调器 - NSPersistentStoreCoordinator
NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]
(2)CoreData 对象映射模型 - NSManagedObjectModel
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
(3)CoreData 托管对象上下文 - NSManagedObjectContext
- 指定队列 _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
- 指定协调器 [_managedObjectContext setPersistentStoreCoordinator:coordinator];
(4)CoreDate 实体描述器 - NSEntityDescription
(5)CoreData 托管对象 - NSManageObject
三、CoreData的4个存储方式:
- SQLite NSSQLiteStoreType
- XML NSXMLStoreType
- Binary NSBinaryStoreType
- 内存存储 NSInMemoryStoreType 这是个及其鸡肋的存储方式。。。。
四、看代码吧~~~配置示例
1、创建一个CoreData管理工具类,方便使用“管理上下文”
@implementation ZQManagerCoreData //单例实现 static ZQManagerCoreData *share; +(instancetype)shareManager { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ share = [[ZQManagerCoreData alloc]init]; }); return share; } //通过getter方法获取上下文: /* 1、生成上下文需要设置持久化存储协调器! 2、生成协调器又需要一个模型 3、新创建一个CoreData选项下的Data Model模型文件 4、把这个模型文件从bundle中加载到 */ -(NSManagedObjectContext *)managedContext { if (_managedContext == nil) { //模型文件的boundle 路径 NSURL *url = [[NSBundle mainBundle] URLForResource:@"Person" withExtension:@"momd"]; //需要一个模型文件 NSManagedObjectModel *model = [[NSManagedObjectModel alloc]initWithContentsOfURL:url]; //创建持久化存储协调器 NSPersistentStoreCoordinator *per = [[NSPersistentStoreCoordinator alloc]initWithManagedObjectModel:model]; //创建对象 _managedContext = [[NSManagedObjectContext alloc]initWithConcurrencyType:NSMainQueueConcurrencyType]; //数据库文件路径 #warning 文件路径放在桌面是随意选的,应该放在沙盒最好 NSURL *fileUrl = [NSURL fileURLWithPath:@"/Users/apple/Desktop/Person/person.db"]; //添加数据库文件路径 [per addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:fileUrl options:nil error:nil]; //设置参数 [_managedContext setPersistentStoreCoordinator:per]; } return _managedContext; }
2、存储数据到数据库
//存储数据 - (void)updata { //通过“实体描述”的类方法 insert 插入数据 /* 1、“实体描述”的类方法,需要实体,要到刚才创建的model文件中去添加实体(点击),同时注意实体的名字首字母必须大写!添加完Entity“实体”以后,设置这个实体的属性,就是对应数据库中的字段 2、“实体描述”的类方法返回的是OC的对象(NSManagedObject),此对象比较特殊,是“游离”对象 3、手动创建一个NSManagedObject的类文件,注意,不是普通的iOS源文件,是通过CoreData选项中的NSManagedObject ect subclass 创建的特殊类。这个类要关联刚才创建的model和model里面的实体,关联在创建的过程中点击就实现了,创建完毕后会多出四个文件(Xcode7新特性,原来是两个文件) 4、导入生成文件的头文件,声明变量接收一下“实体描述”的类方法返回的值 5、对这个对象进行属性操作,就是对数据库中的字段进行操作了! 6、最后,使用“管理上下文”保存,就真正的写入数据库了。 */ Person *person = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:[ZQManagerCoreData shareManager].managedContext]; //修改person对象的属性 person.name = @"lisi"; person.age = @(18); //告诉数据库存储数据 [[ZQManagerCoreData shareManager].managedContext save:nil]; }
3、从数据库中读取
//取数据 fetch - (void)fetch { /* 1、通过“管理上下文” 执行 “请求” 实现取数据 2、创建一个“请求”,需要配置三个属性 (1)需要一个实体描述,和保存时一样 (2)需要一个谓词,设置检索的条件 (3)需要一个排序,将什么属性,按照什么方式排序 3、查询结果是数组,拿数组接一下,数组里面是满足条件的对象(NSManageObject,这里是子类Person) */ //需要一个查询请求 NSFetchRequest *fetchrequest = [[NSFetchRequest alloc]init]; //需要一个实体描述 NSEntityDescription *entity = [NSEntityDescription entityForName:@"Person" inManagedObjectContext:[ZQManagerCoreData shareManager].managedContext]; fetchrequest.entity = entity; //需要一个谓词 相当于SQL语句中的where 条件判断 NSPredicate *pre = [NSPredicate predicateWithFormat:@"age = %@",@"18"]; fetchrequest.predicate = pre; //需要一个排序 NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:YES]; fetchrequest.sortDescriptors = @[sort]; //执行查询请求 NSArray *tempArray = [[ZQManagerCoreData shareManager].managedContext executeFetchRequest:fetchrequest error:nil]; //打印结果 for (Person *person in tempArray) { NSLog(@"person = %@",person.name); } }
另外,Xcode的友好提示:输入关键字 fetch ,系统会提示使用CoreData代码块,可以自动填充上面的取数据代码~~