CoreData是iOS3.0后引入的数据持久化解决方案, 是一种对象关系映射(ORM), 例如Java后台中的hibernate, iOS中ORM框架首先CoreData, 这是官方推荐的 不需要借助第三方框架,实际上是对sqlite的封装,提供了更高级的持久化方式, 在数据库操作时, 不需要使用sql语句, 也可以直接操作数据库
ORM框架的作用:将关系数据库中的表(实体)转换成程序中的对象, 其本质还是对数据库的操作, CoreData将对象关系的映射简化了
使用CoreData进行数据库存取并不需要手动创建数据库, 这个过程完全有CoreData框架完成, 开发人员面对的是模型, 主要的工作就是把模型创建起来, 具体的数据库如何创建也不用管,
CoreData与SQLite相比较, SQLite比较原始, 操作比较复杂, 使用的是C的函数对数据库进行的操作, 但是CoreData不能跨平台, SQLite能够跨平台, 可控性更强, 更加轻量级.
下面简单的学习下CoreData的使用:
其中 各个对象的作用:(NSManagerObjectContext 比较重要)
Persistent Object Store:可以理解为存储持久对象的数据库(例如SQLite,注意Core Data也支持其他类型的数据存储,例如xml、二进制数据等)。
Managed Object Model:对象模型,对应Xcode中创建的模型文件。
Persistent Store Coordinator:对象模型和实体类之间的转换协调器,用于管理不同存储对象的上下文。
Managed Object Context:对象管理上下文,负责实体对象和数据库之间的交互。
模型创建的过程中注意:
实体对象不需要创建ID主键,Attributes中应该是有意义属性(创建过程中应该考虑对象的属性而不是数据库中表有几个字段,尽管多数属性会对应表的字段)。
所有的属性应该指定具体类型(尽管在SQLite中可以不指定),因为实体对象会对应生成ObjC模型类。
实体对象中其他实体对象类型的属性应该通过Relationships建立,并且注意实体之间的对应关系(例如一个用户有多条微博,而一条微博则只属于一个用户,用户和微博形成一对多的关系)。
每个实体类系统自动生成了4个文件User.h, User.m (User的CoreDataProperties的类目)
需要注意的是以下几点:
所有的实体类型都继承于NSManagedObject,每个NSManagedObject对象对应着数据库中一条记录。
集合属性(例如User中的status)生成了访问此属性的分类方法。
使用@dynamic代表具体属性实现,具体实现细节不需要开发人员关心。
CoreData的增删改查的操作主要是基于NSManagerObjectContext, 创建上下文, 保存数据
这里可以使用Appdelegate提供的NSManagerObjectContext这个对象
[objc] view plain copy print?
<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拓展
[objc] view plain copy print?
<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>
[objc] view plain copy print?
<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>
[objc] view plain copy print?
<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>
NSPredicate用于查询和过滤
在SQL中作为查询条件通常用WHERE,但在COREDATA中作为查询条件就可以用到NSPredicate.
NSPredicate 不单可以和COREDATA中的FetchRequest 配合使用。也可以与NSArray配合使用。
NSPredicate 中支持的关键词和条件符:
如:
NSPredicate * qcondition= [NSPredicate predicateWithFormat:@"salary >= 10000"];
如:
@"employee.name BEGINSWITH[cd] '李'" //姓李的员工
@"employee.name ENDSWITH[c] '梦'" //以梦结束的员工
@"employee.name CONTAINS[d] '宗'" //包含有"宗"字的员工
注:[c]不区分大小写[d]不区分发音符号即没有重音符号[cd]既不区分大小写,也不区分发音符号。
如:
@"salary BWTEEN {5000,10000}"
@"em_dept IN '开发'"
如:
NSArray * test = =[NSArray arrayWithObjects: @"guangzhou", @"beijing", @"shanghai", nil];
@"SELF='beijing'"
LIKE 使用?表示一个字符,*表示多个字符,也可以与c、d 连用。
如:
@"car.name LIKE '?he?'" //四个字符中,中间为he
@"car.name LIKE '*jp'" //以jp结束
如:
NSString *regex = @"^E.+e$";//以E 开头,以e 结尾的字符。
NSPredicate *pre= [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
if([pre evaluateWithObject: @"Employee"]){
NSLog(@"matches YES");
}else{
NSLog(@"matches NO");
}
如:
@"employee.name = 'john' AND employee.age = 28"
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语句打印在输出面板
。