CoreData框架, 具有一种对象<-->关系映射机制, 即能够将OC对象转化为数据保存在SQLite(数据库)中, 同时也能够将SQLite中的数据还原为OC对象, 而在此相互转化过程中, 我们无需写繁琐的sql语句.
接下来以单表的增删改查为例:
如果你一开始就能预测到你得工程会用到数据库, 那么创建工程之时, 请不要忽视Xcode对你善意的提醒:
当然, 如果你在创建工程之初, 操作过快而忽略了这个, 也是可以添加的:
这样, CoreData的模型文件就创建号了. 在数据库中, 操作的对象叫"表", 而在CoreData中, 操作的对象叫做"Entity"; 表中字段, 对应于"Entity"中的"Attribute". 工程中有了模型文件, 接下来就是"Attribute"的设置了, 都是可视化的操作, 很简单:
如上图, 创建一个包含三个属性(Attribute)的名为"Person"的实体(Entity), 各属性对应得数据类型如上图, 模型文件 实体 属性 都创建好了, 接下来就是coding了:
导入CoreData库及头文件:
#import <CoreData/CoreData.h>
搭建上下文环境: 创建NSManagedObjectContext的实例, 之后的增删改查都是基于此实例:
// 加载模型文件
NSManagedObjectModel *model = [NSManagedObjectModel mergedModelFromBundles:nil];
// 初始化NSPersistentStoreCoordinator
NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
// 沙盒路径的Documents文件夹
NSString *docs = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
// 数据库文件的绝对路径
NSURL *url = [NSURL fileURLWithPath:[docs stringByAppendingPathComponent:@"person.data"]];
// 添加持久化存储库,这里使用SQLite作为存储库
NSError *error = nil;
NSPersistentStore *store = [psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:url options:nil error:&error];
if (store == nil) { // 直接抛异常
[NSException raise:@"添加数据库错误" format:@"%@", [error localizedDescription]];
}
// 初始化上下文,设置persistentStoreCoordinator属性
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];
context.persistentStoreCoordinator = psc;
添加数据:
// 传入上下文,创建一个Person实体对象
NSManagedObject *person = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:context];
// 设置Person的简单属性
[person setValue:@"Macro" forKey:@"name"];
[person setValue:@(26) forKey:@"age"]; // 非对象数据要注意
[person setValue:@"male" forKey:@"sex"];
// 利用上下文对象,将数据同步到持久化存储库
error = nil;
BOOL success = [context save:&error];
if (!success) {
[NSException raise:@"访问数据库错误" format:@"%@", [error localizedDescription]];
} else {
NSLog(@"保存成功");
}
查询数据:
// 初始化一个查询请求
NSFetchRequest *request = [[NSFetchRequest alloc] init];
// 设置要查询的实体
request.entity = [NSEntityDescription entityForName:@"Person" inManagedObjectContext:context];
// 执行请求
error = nil;
NSArray *objs = [context executeFetchRequest:request error:&error]; // 查询结果是数组
if (error) {
[NSException raise:@"查询错误" format:@"%@", [error localizedDescription]];
}
// 遍历数据
for (NSManagedObject *obj in objs) {
NSLog(@"name:%@ age:%@", [obj valueForKey:@"name"], [obj valueForKey:@"age"]);
}
如果需要添加查询约束, 则可设置request的相关属性值即可:
// 设置排序(按照age降序)
NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:NO];
request.sortDescriptors = [NSArray arrayWithObject:sort];
// 设置条件过滤(模糊查询) 数据库SQL语句中的%要用*来代替
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name like %@", @"*Ma*"];
request.predicate = predicate;
删除数据:
// 遍历数据 在遍历的基础上删除
for (NSManagedObject *obj in objs) {
if ([[obj valueForKey:@"name"] isEqualToString:@"Macro"]) {
[context deleteObject:person];
error = nil;
[context save:&error]; // 删除之后一定要保存(可以在删除完全之后,统一保存)
if (error) {
[NSException raise:@"删除错误" format:@"%@", [error localizedDescription]];
} else {
NSLog(@"删除成功");
}
}
}
直接删除实例对象:
[context deleteObject:person];
error = nil;
[context save:&error];
if (error) {
[NSException raise:@"删除错误" format:@"%@", [error localizedDescription]];
} else {
NSLog(@"删除成功");
}
修改数据:(和删除类似)
for (NSManagedObject *obj in objs) {
if ([[obj valueForKey:@"name"] isEqualToString:@"Macro"]) {
[obj setValue:@"MacroHong" forKey:@"name"];
error = nil;
[context save:&error];
if (error) {
[NSException raise:@"更新错误" format:@"%@", [error localizedDescription]];
} else {
NSLog(@"更新成功");
}
}
}
如何查看上述操作的SQL语句呢?
"Edit Scheme..." --> "Run" --> "Arguments" 添加2项
-com.apple.CoreData.SQLDebug
1
这样在Output窗口中就可以看得到每一步操作的SQL语句了
默认情况下的用键-值对来存取数据, 可能满足不了项目的需求, 因为一般情况下都需要在数据模型层进行业务操作, 这样就必须创建NSManagedObject的子类:
创建完成之后, 工程目录下会自动多出这四个文件,(Xcode7之前应该没有上面两个类别文件), 这样就可以操作对象属性来进行相关操作了:
Person *person = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:context];
person.name = @"Macro";
person.age = @(26);
person.sex = @"male";
// 最后调用[context save&error];同步到数据库即可