<strong> CoreData</strong>
1.CoreData
苹果自带的 管理数据库的工具
使用Core Data有很多原因,其中最简单的一条就是:它能让你为Model层写的代码的行数减少为原来的50%到70%。 这归功于之前提到的Core Data的特性。更妙的是,对于上述特性你也既不用去测试,也不用花功夫去优化。
Core Data拥有成熟的代码,这些代码通过单元测试来保证品质。通过了几个版本的发布,已经被高度优化。 它能利用Model层的信息和运行时的特性,而不通过程序层的代码实现。 除了提供强大的安全支持和错误处理外,它还提供了最优的内存扩展性,可实现有竞争力的解决方案。不使用Core Data的话,你需要花很长时间来起草自己的方案,解决各种问题,这样做效率不高。
另外:
coreData主要是iOS对sqlite数据库的封装。
coreData有对象-关系的映射的功能,能把OC的对象存储成数据库或xml等
如果数据存储使用的是coreData,那么读取时可以不使用SQL语句。
coreData 类似于 我们之前使用的FMDB
关于Core Data常见的误解:
1) Core Data不是一个关系型数据库,也不是关系型数据库管理系统(RDBMS)。
Core Data 为数据变更管理、对象存储、对象读取恢复的功能提供了支持。 它可以使用SQLite作为持久化存储的类型。 它本身并不是一个数据库(这点很重要,比如,你可以使用Core Data来记录数据变更,管理数据,但并不能用它向文件内存储数据)。
2)
它并不能取代你写代码的工作。虽然可以纯粹使用XCode的数据建模工具和Interface Builder来编写复杂程序,但在更多的程序中,你都自己动手写代码。

1,应用程序先创建或读取模型文件(后缀为xcdatamodeld)生成 NSManagedObjectModel 对象。从模型文件(后缀为 xcdatamodeld)读取。
2,然后生成 NSManagedObjectContext 和 NSPersistentStoreCoordinator 对象,前者对用户透明地调用后者对数据文件进行读写。
3,NSPersistentStoreCoordinator 负责从数据文件(xml, sqlite,二进制文件等)中读取数据生成 Managed Object,或保存 Managed Object 写入数据文件。
4,NSManagedObjectContext 参与对数据进行各种操作的整个过程,它持有 Managed Object。我们通过它来监测 Managed Object。监测数据对象有两个作用:支持 undo/redo 以及数据绑定。这个类是最常被用到的。
5,Array Controller, Object Controller, Tree Controller 这些控制器一般与 NSManagedObjectContext 关联,因此我们可以通过它们在 nib 中可视化地操作数据对象。
代码步骤
1.导入 库CoreData.framework 和头文件
2.这样托管对象模型知道所有当前工程中用到的托管对象的定义
创建一个NSManagedObjectModel 数据模型文件
//1.创建数据模型文件-》new file->core Data--》选中Data Model,创建文件 (User.xcdatamodeld)在里面创建 数据模型实例Entity(UserModel)
//2.创建跟数据模型文件关联的数据模型类new file->core Data->选中 NSManagedObject of subclass --》关联上User.xcdatamodeld数据模型文件中的UserModel 实例
//3.用代码初始化CoreData
//3.1 导入 #import <CoreData/CoreData.h>
//3.2 从沙盒包内 读取数据模型文件
/*
有两种方式:
a.//获取到coreData文件的路径,并转换成url
//在包内User.xcdatamodeld会转化为 User.momd
NSString *coreDataPath =[[NSBundle mainBundle] pathForResource:@"User" ofType:@"momd"];
//加载coreData文件中的数据,转成model
NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:[NSURL fileURLWithPath:coreDataPath]];
b.NSManagedObjectModel *model = [NSManagedObjectModel mergedModelFromBundles:nil];
中的nil表示连接项目中所有的 .xcdatamodeld 文件为一个datamodel,这是一个非常好的方法,把多个entity放在各自的xcodemodel文件中分开管理,然后用这个函数连接起来生成一个datamodel,这样就可以对应一个persistentStore。
*/
//NSLog(@"data:%@",[[NSBundle mainBundle] pathForResource:@"User" ofType:@"momd"]);
//3.2获取 数据模型文件
3.创建协调器
NSPersistentStoreCoordinator
4.//将coreData数据映射到数据库
addPersistentStoreWithType
5.//创建上下文托管对象
NSManagedObjectContext
6增删改查
下面是一些例子:
//
// CoreDataManager.m
// CoreDataDemo
//
#import "CoreDataManager.h"
#import "StudentModel.h"
@implementation CoreDataManager
//单例函数
+ (instancetype)sharedManager {
static CoreDataManager *manager = nil;
@synchronized(self) {
if (manager == nil) {
manager = [[self alloc] init];
}
}
return manager;
}
//初始化数据库 ->一旦 获取 管理对象 数据库就应该 创建好了,应该在初始化函数进行
/*
1.创建 数据模型 文件
2.根据数据模型 文件 设计 model
3.初始化 CoreData
3.1 #import <CoreData/CoreData.h>
3.2 获取数据模型文件(沙盒包内)
MyData.xcdatamodeld在沙盒包内 叫做MyData.momd
3.3 根据数据模型文件 实例化 存储协调器
3.4 创建数据库sqlite 类型的文件
3.5 创建上下文管理对象 关联 协调器
3.6 通过上下文 进行 数据库的增删改查
*/
- (instancetype)init {
if (self = [super init]) {
//1.获取 数据模型文件 路径
#if 0
//方法1// MyData.xcdatamodeld在沙盒包内中变成 xx.momd
NSString *path = [[NSBundle mainBundle] pathForResource:@"MyData" ofType:@"momd"];
NSManagedObjectModel *modelFile = [[NSManagedObjectModel alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path]];
#else
//获取沙盒包内 中 所有的xxx.xcdatamodeld数据模型 文件
NSManagedObjectModel *modelFile = [NSManagedObjectModel mergedModelFromBundles:nil];
#endif
//2.实例化 存储协调器 管理数据模型文件
NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:modelFile];
//2.1协调器 增加 存储类型 数据库
NSString *path = [NSHomeDirectory() stringByAppendingFormat:@"/Documents/data.sqlite"];
//NSSQLiteStoreType sqlite 数据类型
NSPersistentStore *store = [coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[NSURL fileURLWithPath:path] options:nil error:nil];
if (!store) {
NSLog(@"创建数据库失败");
}
//3.创建上下文
self.context = [[NSManagedObjectContext alloc] init];
//设置 管理协调器
self.context.persistentStoreCoordinator = coordinator;
}
return self;
}
//增删改查
#pragma mark - 增加
- (void)insertDataWithName:(NSString *)name
score:(double)score
headimage:(NSData *)headimage {
//使用CoreData 的时候 模型不能按照下面的形式创建 会崩溃
// StudentModel *model = [[StudentModel alloc] init];
// model.name = @"xxx";
// 上下文管理对象 通过 NSEntityDescription 来向数据库 动态增加一个数据模型对象StudentModel
//NSEntityDescription 内部 会动态为 数据模型增加setter和getter方法
StudentModel *model = (StudentModel *)[NSEntityDescription insertNewObjectForEntityForName:@"StudentModel" inManagedObjectContext:self.context];
//赋值
model.name = name;
model.score = @(score);
model.headimage = headimage;
//上面 是 对内存做了增加
//保存到本地磁盘数据库 (增删改 都要对数据库进行保存 才能写入磁盘)
[self saveDataWithType:@"insert"];
}
- (void)saveDataWithType:(NSString *)type {
NSError *error = nil;
BOOL ret = [self.context save:&error];
if (!ret) {//保存失败
NSLog(@"%@ error:%@",type,error.localizedDescription);
}
}
#pragma mark - 删除
//根据名字删除
- (void)deleteDataWithName:(NSString *)name {
//先找再删除
NSArray *arr = [self fetchDataWithName:name];
//遍历
for (StudentModel *model in arr) {
//从内存数据删除
[self.context deleteObject:model];
}
//保存 同步到本地磁盘
[self saveDataWithType:@"delete"];
}
#pragma mark - 修改
//根据名字修改其他数据
- (void)updateDataWithName:(NSString *)name
score:(double)score
headimage:(NSData *)headimage {
//先找再修改
NSArray *arr = [self fetchDataWithName:name];
//遍历
for (StudentModel *model in arr) {
//直接修改找到的model 这些model 都在数据库内存中
model.score = @(score);
model.headimage = headimage;
}
//保存 同步到本地磁盘
[self saveDataWithType:@"update"];
}
#pragma mark - 查找
//根据名字找
- (NSArray *)fetchDataWithName:(NSString *)newName {
//创建一个查询请求
NSFetchRequest *request = [[NSFetchRequest alloc] init];
//设置 要查询的实体(数据模型) 向哪一类数据模型进行查询
request.entity = [NSEntityDescription entityForName:@"StudentModel" inManagedObjectContext:self.context];
if (newName) {
//设置谓词 根据过滤条件来查找
//@"name like xiaohong"--->谓词 去 StudentModel 的对象 中 找属性名是name 的属性 的值 是不是xiaohong
//@"score like 100"
#if 0
//模糊查询 要分开写条件 '*xiaohong*'
NSString * str = [NSString stringWithFormat:@"name like '*%@*'",newName];
NSPredicate *predicate = [NSPredicate predicateWithFormat:str];
#else
//设置谓词 -》过滤查询
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name like %@",newName];
#endif
request.predicate = predicate;
}
//设置排序准则(如果要想排序 需要设置排序准则)
//按照分数降序排 key 就是对象的属性名
NSSortDescriptor*sort1 = [NSSortDescriptor sortDescriptorWithKey:@"score" ascending:NO];
NSSortDescriptor*sort2 = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:NO];
//先按照sort1排序 如果score 有相同的再按照sort2排
request.sortDescriptors = @[sort1,sort2];
//没有设置谓词的话 表示查询所有的StudentModel
//执行 查询请求 返回一个数组
NSArray *arr = [self.context executeFetchRequest:request error:nil];
return arr;
}
@end
//
// CoreDataManager.h
// CoreDataDemo
//
#import <Foundation/Foundation.h>
//把 官方自带的CoreData 封装 进行增删改查
#import <CoreData/CoreData.h>
@interface CoreDataManager : NSObject
//CoreData 上下文
@property (nonatomic,strong) NSManagedObjectContext *context;
//单例函数
+ (instancetype)sharedManager;
//增删改查
#pragma mark - 增加
- (void)insertDataWithName:(NSString *)name
score:(double)score
headimage:(NSData *)headimage;
#pragma mark - 删除
//根据名字删除
- (void)deleteDataWithName:(NSString *)name;
#pragma mark - 修改
//根据名字修改其他数据
- (void)updateDataWithName:(NSString *)name
score:(double)score
headimage:(NSData *)headimage;
#pragma mark - 查找
- (NSArray *)fetchDataWithName:(NSString *)newName;
@end