说道IM,就不得不说一下iOS的数据存储方式,不知道大家有没有发现,当你换了手机,在微信上重新登录你的账号,你的聊天记录全都不见了,而QQ则不是这样,这是为什么呢?大家肯定能想到,QQ是在服务端存储的,而微信是在本地存储的。所以这里就牵扯到了iOS的数据持久化方式。今天我就介绍其中的一种:CoreData。
概念:
什么是CoreData呢?CoreData是个框架,并不是数据库,它使开发者可以把数据当做对象来操作,而不在乎数据在磁盘中的存储方式。类似于Hibernate,CoreData提供了一种对象-关系映射(ORM)的机制,避免了开发者去书写SQL语句,将其面向对象化。由CoreData提供的数据对象叫做托管对象(Managed Object),而CoreData本身则位于你的应用程序和持久化存储区(Persistent Store)之间。为了把数据从托管对象映射到持久化存储区中,CoreData需要使用托管对象模型。所有的托管对象都必须位于托管对象上下文(Managed Object Context)里面,而托管对象上下文又位于高速的易失性存储器里面,也就是位于RAM中。
为什么需要有托管对象上下文呢?原因之一就是磁盘与RAM之间传输数据时会有开销。磁盘读写速度比RAM慢得多,所以不应该频繁地访问它。有了托管对象上下文,就可以非常迅速地获取到了。但它的缺点在于,开发者必须在托管对象上下文上面定期调用save方法,以将变更后的数据写回磁盘。托管对象上下文的另一个功能是记录开发者对托管对象所做的修改,以提供完整的撤销和重做支持。
项目中添加Core Data:
添加CoreData有2种方式:
(1)新建项目的时候勾选Use Core Data,如下图,这样系统就会自动为你创建Core Data相关的文件。
(2)如果项目开始时没有勾选Use Core Data,也没有关系,可以手动添加。
a.新建Data Model(相当于数据库)文件,操作过程如下图
b.新建实体(Entity,相当于数据库中的表),这个过程相当于在数据库中新建表,然后在表中添加字段。
c.完成前2步之后,数据库、数据库中的表以及表中的字段都已经建好了,之前我们已经介绍过了,Core Data提供了一种对象-关系映射(ORM),所以我们还需要新建一个对象与之对象。(这里有个小地方需要注意一下,Xcode8 Core Data里面没有了NSManagedObject subclass这个选项,需要在菜单栏的Editor->Create NSManagedObject Subclass进行创建)
ok,Core Data创建工作已经完成了,下面就来看一下怎么使用。
基本用法:
Core Data其实是对SQLite进行的封装,所以基本用法无外乎CURD(增删改查),下面我们就直接上代码,来看一下Core Data的基本用法。
(1)在viewDidLoad中添加如下代码进行初始化。
//1、创建模型对象
//获取模型路径
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"Company" withExtension:@"momd"];
//根据模型文件创建模型对象
NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
//2、创建持久化助理
//利用模型对象创建助理对象
NSPersistentStoreCoordinator *store = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
//数据库的名称和路径
NSString *docStr = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *sqlPath = [docStr stringByAppendingPathComponent:@"Employee.sqlite"];
NSLog(@"path = %@", sqlPath);
NSURL *sqlUrl = [NSURL fileURLWithPath:sqlPath];
//设置数据库相关信息
[store addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:sqlUrl options:nil error:nil];
//3、创建上下文
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
//关联持久化助理
[context setPersistentStoreCoordinator:store];
_context = context;
(2)添加数据
// 添加员工
- (IBAction)addEmployee:(id)sender {
Employee *emp = [NSEntityDescription insertNewObjectForEntityForName:@"Employee" inManagedObjectContext:_context];
emp.name = _nameTxt.text;
emp.birthday = [NSDate date];
emp.age = [_ageTxt.text intValue];
// 保存
NSError *error = nil;
[_context save:&error];
if (error) {
NSLog(@"保存失败:%@", error);
} else {
NSLog(@"保存成功");
}
}
(3)删除数据
// 删除员工
- (IBAction)deleteEmployee:(id)sender {
// 1.NSFetchRequest 抓取请求
NSFetchRequest *fetchRequest = [Employee fetchRequest];
// 2.过滤
NSPredicate *pre = [NSPredicate predicateWithFormat:@"name = %@", @"Lisi"];
fetchRequest.predicate = pre;
// 3.执行抓取请求
NSError *error = nil;
NSArray *employees = [_context executeFetchRequest:fetchRequest error:&error];
if (error) {
NSLog(@"获取失败!%@", error);
} else {
if (employees.count == 0) {
NSLog(@"没有查询到该员工!");
return;
}
for (Employee *emp in employees) {
[_context deleteObject:emp];
}
[_context save:&error];
if (error) {
NSLog(@"删除失败:%@", error);
} else {
NSLog(@"删除成功");
}
}
}
(4)修改数据
// 更新员工
- (IBAction)updateEmployee:(id)sender {
// 1.NSFetchRequest 抓取请求
NSFetchRequest *fetchRequest = [Employee fetchRequest];
// 2.过滤
NSPredicate *pre = [NSPredicate predicateWithFormat:@"name = %@", @"zhangsan"];
fetchRequest.predicate = pre;
// 3.执行抓取请求
NSError *error = nil;
NSArray *employees = [_context executeFetchRequest:fetchRequest error:&error];
if (error) {
NSLog(@"获取失败!%@", error);
} else {
if (employees.count == 0) {
NSLog(@"没有查询到该员工!");
return;
}
for (Employee *emp in employees) {
emp.age = 100;
}
[_context save:&error];
if (error) {
NSLog(@"更新失败:%@", error);
} else {
NSLog(@"更新成功");
}
}
}
(5)查询数据
// 查询员工
- (IBAction)loadEmployee:(id)sender {
// 1.NSFetchRequest 抓取请求
NSFetchRequest *fetchRequest = [Employee fetchRequest];
// 2.过滤
// NSPredicate *pre = [NSPredicate predicateWithFormat:@"name = %@", @"zhangsan"];
// fetchRequest.predicate = pre;
// 3.排序
fetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"age" ascending:NO]];
// 4.执行抓取请求
NSError *error = nil;
NSArray *employees = [_context executeFetchRequest:fetchRequest error:&error];
if (error) {
NSLog(@"获取失败!%@", error);
} else {
for (Employee *emp in employees) {
NSLog(@"名字:%@, 年龄:%d, 生日:%@", emp.name, emp.age, emp.birthday);
}
}
}
代码里都有详细的注释,我就不过多解释了,也不是很难,只要理解了Core Data的概念,其他的都还算比较好理解。