iOS 数据持久化 CoreData
Posted HeathHsia
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS 数据持久化 CoreData相关的知识,希望对你有一定的参考价值。
本文是关于http://www.cnblogs.com/kenshincui/p/4077833.html#autoid-3-1-0整理的
CoreData是ios3.0后引入的数据持久化解决方案, 是一种对象关系映射(ORM), 例如java后台中的Hibernate, iOS中ORM框架首先CoreData, 这是官方推荐的 不需要借助第三方框架,实际上是对sqlite的封装,提供了更高级的持久化方式, 在数据库操作时, 不需要使用sql语句, 也可以直接操作数据库
ORM框架的作用:将关系数据库中的表(实体)转换成程序中的对象, 其本质还是对数据库的操作, CoreData将对象关系的映射简化了
使用CoreData进行数据库存取并不需要手动创建数据库, 这个过程完全有CoreData框架完成, 开发人员面对的是模型, 主要的工作就是把模型创建起来, 具体的数据库如何创建也不用管,
CoreData与SQLite相比较, SQLite比较原始, 操作比较复杂, 使用的是C的函数对数据库进行的操作, 但是CoreData不能跨平台, SQLite能够跨平台, 可控性更强, 更加轻量级.
下面简单的学习下CoreData的使用:
1. 创建工程的时候要勾选 user CoreData
2. 在Appdelegate中会自动生成以下对象和方法
其中 各个对象的作用:(NSManagerObjectContext 比较重要)
- Persistent Object Store:可以理解为存储持久对象的数据库(例如SQLite,注意Core Data也支持其他类型的数据存储,例如xml、二进制数据等)。
- Managed Object Model:对象模型,对应Xcode中创建的模型文件。
- Persistent Store Coordinator:对象模型和实体类之间的转换协调器,用于管理不同存储对象的上下文。
- Managed Object Context:对象管理上下文,负责实体对象和数据库之间的交互。
3. 创建实体模型和关系:
模型创建的过程中注意:
- 实体对象不需要创建ID主键,Attributes中应该是有意义属性(创建过程中应该考虑对象的属性而不是数据库中表有几个字段,尽管多数属性会对应表的字段)。
- 所有的属性应该指定具体类型(尽管在SQLite中可以不指定),因为实体对象会对应生成ObjC模型类。
- 实体对象中其他实体对象类型的属性应该通过Relationships建立,并且注意实体之间的对应关系(例如一个用户有多条微博,而一条微博则只属于一个用户,用户和微博形成一对多的关系)。
4. 根据上面的模型文件(.xcdatamodeld文件)生成具体的实体类.
每个实体类系统自动生成了4个文件User.h, User.m (User的CoreDataProperties的类目)
需要注意的是以下几点:
- 所有的实体类型都继承于NSManagedObject,每个NSManagedObject对象对应着数据库中一条记录。
- 集合属性(例如User中的status)生成了访问此属性的分类方法。
- 使用@dynamic代表具体属性实现,具体实现细节不需要开发人员关心。
5. 创建好实体和关系, 就可以对数据进行增删改查的操作了:
CoreData的增删改查的操作主要是基于NSManagerObjectContext, 创建上下文, 保存数据
这里可以使用Appdelegate提供的NSManagerObjectContext这个对象
增加数据: 需要调用NSEntityDescription返回一个实体对象, 然后设置对象的属性, 保存上下文(进行增删改操作的时候, 一定要调用管理上下文的保存方法, 否则操作不会执行)
<span style="font-size:18px;">// 添加数据 - (IBAction)add:(id)sender { // 用NSEntityDescription创建实体对象 User *user = [NSEntityDescription insertNewObjectForEntityForName:@"User" inManagedObjectContext:self.managerObjectContext]; user.name = @"Xia"; user.age = @"18"; user.time = [NSDate dateWithTimeIntervalSinceNow:0]; NSError *error; // 保存上下文 if (![self.managerObjectContext save:&error]) { NSLog(@"添加过程中的错误信息---%@", error.localizedDescription); } }</span>
查询数据: 通过谓词来实现的, 首先创建一个请求, 设置请求的谓词, 调用上下文执行
注意: 下面有关于NSPredicate拓展
<span style="font-size:18px;">// 查询数据 - (IBAction)equery:(id)sender { // 查询获取请求, 设置查询哪个实体 EntityName NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"User"]; // NSFetchRequest 有个属性 谓词 predicate(NSPredicate类型) // 类似于查询语句的查询条件 用来条件查询 // 查询 user表中 name是Xia的User request.predicate = [NSPredicate predicateWithFormat:@"name='Xia'"]; // 也可以使用下面的查询语句格式 // NSString *name = @"Xia"; // request.predicate = [NSPredicate predicateWithFormat:@"name like [cd] %@", name]; NSArray *array = [self.managerObjectContext executeFetchRequest:request error:nil]; }</span>
删除数据
<span style="font-size:18px;">// 删除数据 - (IBAction)delete:(id)sender { // 先获取表里的所有数据 NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"User"]; NSArray *array = [self.managerObjectContext executeFetchRequest:request error:nil]; // 对表里数据的数组进行遍历 for (User *user in array) { // 条件删除 if ([user.name isEqualToString:@"Xia"]) { [self.managerObjectContext deleteObject:user]; } } NSError *error; // 保存上下文 if (![self.managerObjectContext save:&error]) { NSLog(@"删除过程中发生的错误信息 ----- %@", error.localizedDescription); } }</span>
更新数据
<span style="font-size:18px;">// 更新数据 - (IBAction)update:(id)sender { // 先获取某个实体 User *user = [self getUserByUserName:@"Xia"]; // 修改实体的属性 user.name = @"Yan"; user.age = @"20"; NSError *error; // 保存上下文 if (![self.managerObjectContext save:&error]) { NSLog(@"更新数据发生错误 错误信息----%@", error.localizedDescription); } } // 通过username 获取 User实体类 - (User *)getUserByUserName:(NSString *)username { // User *user = [[User alloc] init]; NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"User"]; NSArray *array = [self.managerObjectContext executeFetchRequest:request error:nil]; for (User *auser in array) { if ([auser.name isEqualToString:username]) { return auser; } } return nil; }</span>
关于NSPreidicate的拓展
NSPredicate用于查询和过滤
在SQL中作为查询条件通常用WHERE,但在COREDATA中作为查询条件就可以用到NSPredicate.
NSPredicate 不单可以和COREDATA中的FetchRequest 配合使用。也可以与NSArray配合使用。
NSPredicate 中支持的关键词和条件符:
1、>,<,>=,<=,= 比较运算符。
如:
NSPredicate * qcondition= [NSPredicate predicateWithFormat:@"salary >= 10000"];
2、字符串操作(包含):BEGINSWITH、ENDSWITH、CONTAINS
如:
@"employee.name BEGINSWITH[cd] '李'" //姓李的员工
@"employee.name ENDSWITH[c] '梦'" //以梦结束的员工
@"employee.name CONTAINS[d] '宗'" //包含有"宗"字的员工
注:[c]不区分大小写[d]不区分发音符号即没有重音符号[cd]既不区分大小写,也不区分发音符号。
3、范围:IN ,BWTEEN
如:
@"salary BWTEEN {5000,10000}"
@"em_dept IN '开发'"
4、自身:SELF,这个只针对字符数组起作用。
如:
NSArray * test = =[NSArray arrayWithObjects: @"guangzhou", @"beijing", @"shanghai", nil];
@"SELF='beijing'"
5、通配符:LIKE
LIKE 使用?表示一个字符,*表示多个字符,也可以与c、d 连用。
如:
@"car.name LIKE '?he?'" //四个字符中,中间为he
@"car.name LIKE '*jp'" //以jp结束
6、正则表达式:MATCHES
如:
NSString *regex = @"^E.+e$";//以E 开头,以e 结尾的字符。
NSPredicate *pre= [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
if([pre evaluateWithObject: @"Employee"]){
NSLog(@"matches YES");
}else{
NSLog(@"matches NO");
}
7、逻辑运算符:AND、OR、NOT
如:
@"employee.name = 'john' AND employee.age = 28"
8、占位符:
NSPredicate *preTemplate = [NSPredicate predicateWithFormat:@"name==$NAME"];
NSDictionary *dic=[NSDictionary dictionaryWithObjectsAndKeys:
@"Name1", @"NAME",nil];
NSPredicate *pre=[preTemplate predicateWithSubstitutionVariables: dic];
占位符就是字典对象里的key,因此你可以有多个占位符,只要key 不一样就可以了。
CoreData的操作会转换为SQL操作, 在Xcode上设置支持CoreData调试
Product-Scheme-Edit Scheme-Run-Arguments中依次添加两个参数(注意参数顺序不能错):-com.apple.CoreData.SQLDebug、1。然后在运行程序过程中如果操作了数据库就会将SQL语句打印在输出面板
。
最后注意:CoreData线程安全问题 和CoreData的版本迁移问题, 下次有时间再整理
以上是关于iOS 数据持久化 CoreData的主要内容,如果未能解决你的问题,请参考以下文章