- CoreData概念.
是一种提供对象关系映射的功能,将OC对象转换成数据,保存在SQLite数据库文件中数据持久化框架,用来解决对象生命周期管理,对象关系图管理,和持久化等方面相关问题的,负责在数据库中存储数据,底层也是类似于SQLite的技术实现.
-
CoreData优点:
1:可视化,不用再写SQL语句,大量简化代码,有undo/redo能力
2:可以实现多种文件格式:NSSQLiteStoreType,NSXMLStoreType
3:与iOS紧密结合,只能用于开发iOS,开发效率会高一点
4:存储内容,以对象形式存储,数据存储结构简单,符合面向对象的思想(持久化:把数据保存到一个文件,而不是内存) CoreData缺点:
CoreData的代码运行效率没直接使用sql代码的运行效率高
- 而之前说过的SQLite
- 是一个轻量级数据库,且功能强大的关系型数据库,很容易被嵌入到应用当中,可移植性高,可在多个平台使用
- 和CoreData框架不一样的是,sqlite是使用程序式的,sqlite的主要操作方法是直接操作数据表
- 基于C接口,使用sql语句,代码繁琐
- 在处理大量数据时,表关系更直观一些
- OC中不是可视化的
下边说一下CoreData的核心对象:
1:. ** NSManagedObjectContext:**(被管理了上下文),操作实际内容(对持久层的一个操作),插入数据,查询数据,删除数据,修改数据,是我们开发中主要交互的类,数据的CRUD都通过这个Context(上下文)去触发命令并返回结果.
2:. NSManagedObjectModel:(被管理的数据模型),包含了各个实体(相当于SQL中的表)的定义信息,包含了实体(表)或者是数据库的结构.添加实体属性(字段),建立属性之间的关系.
- 操作方法:视图编辑器,也可用代码.
(构建数据库的表结构,表字段类型,表与表之间的关系等,凡是和数据结构有关系的定义,通通都通过这个类来管理)
3:. NSPersistentStoreCoordinator:(持久化存储助理)相当于数据库的连接器
- 作用:设置数据存储的名字,位置,存储方法,存储时机.
- 原理:从下层文件取出数据,交给上层的被管理对象上下文.实际上,这个类才是真正意义上跟数据库打交道的(.sqlite文件),主要根据NSManagedObjectModel执行表结构的建立,通过 NSManagedObjectContext的命令执行数据交互.
下边我还是通过一些简单的例子给以说明下.(这里我用的是多表关联)
说之前先插一句:多表关联
CoreData在存储复杂数据关系时,一张表难以满足需求,此时就需要了解使用CoreData的多表关联
eg:学科表和课程表的关系:一门学科里有多个课程(一对多);而单一课程只能对应一门学科(一对一)
表之间就是靠这种相互约束的关系建立关联.
首先就是在建工程时勾选UseCoreData按钮.
其次就是在工程中生成的CoreData______.xcdatamodeld文件里对实体进行创建关联
把创建好的实体生成模型
通过上图操作可以生成对应的文件.注意文件中的属性类型一定要是关联好的实体名,否则删了重建
下边的代码分别实现了数据的CRUD
- (void)add{
//创建实体描述
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Subject" inManagedObjectContext:self.managedObjectContext];
//创建subject实体对象,然后告诉上下文,让它做好添加准备,然后将subject实体对象添加到数据库中
//创建subject实体
Subject *sub = [[Subject alloc]initWithEntity:entity insertIntoManagedObjectContext:self.managedObjectContext];
//给对象赋值
sub.subjectName = @"iOS";
//将课程对象通过实体描述类创建出来
Course *course = [NSEntityDescription insertNewObjectForEntityForName:@"Course" inManagedObjectContext:self.managedObjectContext];
course.courseName = @"oc语言";
Course *course1 = [NSEntityDescription insertNewObjectForEntityForName:@"Course" inManagedObjectContext:self.managedObjectContext];
course1.courseName = @"c语言";
//将这两门课程放入集合当中存储,赋值
NSSet *set = [NSSet setWithObjects:course,course1, nil];
//给集合赋值
sub.subject = set;
BOOL result = [self.managedObjectContext save:nil];
if (result) {
NSLog(@"插入数据成功");
}else{
NSLog(@"插入数据失败");
}
}
#pragma mark---删-----
- (void)delete{
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Subject"];
//找到删除的条件
request.predicate = [NSPredicate predicateWithFormat:@"subjectName = %@",@"H5"];
//由context根据删除条件执行相关操作
NSArray *array = [self.managedObjectContext executeFetchRequest:request error:nil];
//遍历结果
for (Subject *sub in array) {
[self.managedObjectContext deleteObject:sub];
}
if ([self.managedObjectContext save:nil]) {
NSLog(@"删除成功");
}else{
NSLog(@"删除失败");
}
}
#pragma mark---改-----
- (void)update{
//实例化一个查询请求
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Subject"];
//设置查询条件
request.predicate = [NSPredicate predicateWithFormat:@"subjectName CONTAINS 'OS'"];//包含内容加单引号
//由context按照查询条件进行相关操作
NSArray *array = [self.managedObjectContext executeFetchRequest:request error:nil];
//遍历结果,更新信息
for (Subject *sub in array) {
//更新信息
sub.subjectName = @"H5";
}
//保存
if ([self.managedObjectContext save:nil]) {
NSLog(@"更新成功");
}else{
NSLog(@"更新失败");
}
}
#pragma mark---查-----
- (void)select{
//实例化一个查询请求
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Subject"];
//设置查询条件
request.predicate = [NSPredicate predicateWithFormat:@"subjectName = 'H5'"];//包含内容加单引号
//读取数据库的游标偏移量,从游标开始读取数据
// request.fetchOffset = 17;
//每次要取多少数据,
// request.fetchLimit = 3;
//从数据库里每次加载2条数据来筛选数据
// request.fetchBatchSize = 2;
//由context按照查询条件进行相关操作
NSArray *array = [self.managedObjectContext executeFetchRequest:request error:nil];
//遍历结果
for (Subject *sub in array) {
NSLog(@"name:%@",sub.subjectName);
}
//保存
if ([self.managedObjectContext save:nil]) {
NSLog(@"查询成功");
}else{
NSLog(@"查询失败");
}
}
代码中用到了谓词,可用谓词进行模糊查询
1.
BEGINSWITH:
检查某个字符串是否以指定的字符串开头(如判断字符串是否以a开头:BEGINSWITH 'a'
)
2.
ENDSWITH:
检查某个字符串是否以指定的字符串结尾
3.
CONTAINS:
检查某个字符串是否包含指定的字符串
4.
LIKE:
检查某个字符串是否匹配指定的字符串模板。其之后可以跟?
代表一个字符和*
代表任意多个字符两个通配符。比如"name LIKE '*ac*'"
,这表示name的值中包含ac则返回YES;"name LIKE '?ac*'"
,表示name的第2、3个字符为ac时返回YES。
5.
MATCHES:
检查某个字符串是否匹配指定的正则表达式。虽然正则表达式的执行效率是最低的,但其功能是最强大的,也是我们最常用的。
6.使用谓词过滤不可变集合和可变集合的区别是:过滤不可变集合时,会返回符合条件的集合元素组成的新集合;过滤可变集合时,没有返回值,会直接剔除不符合条件的集合元素
说了这么多,那么对于一开始创建工程时,没有勾选Use Core Data选项的工程,想要中途创建CoreData文件,要怎么办呢?
- 创建CoreData框架的步骤:
- 1,创建模型文件
2,添加实体(这步和上面介绍的操作一样)
3,创建实体类
4,生成上下文,关联模型文件生成数据库
我是先声明一个管理上下文的属性,方便进行CURD的操作使用
@property (nonatomic, strong) NSManagedObjectContext *managedObject;
#pragma mark----使用NSManagedObjectContext方法,如果bundles为nil会把bundles里面的所有模型文件的表放在一个数据库)
//创建context
- (void)creatContext{
//创建上下文
_managedObject = [[NSManagedObjectContext alloc]initWithConcurrencyType:(NSMainQueueConcurrencyType)];
//实例化model
NSManagedObjectModel *model = [NSManagedObjectModel mergedModelFromBundles:nil];
//数据存储调度器(持久化助理)
//store添加路径
NSString *doccumentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject ];
// NSLog(@"%@",doccumentPath);
NSString *coredatapath = [doccumentPath stringByAppendingPathComponent:@"movie.sqlite"];
NSPersistentStoreCoordinator *store = [[NSPersistentStoreCoordinator alloc]initWithManagedObjectModel:model];
self.managedObject.persistentStoreCoordinator = store;
[store addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[NSURL fileURLWithPath:coredatapath] options:nil error:nil];
}
- 5,保存对象到数据库
- 6,从数据库获取对象
- 7更新,进行CURD操作(这些方法和上面的方法相同,只不过是在创建实体描述时,里边的管理上下文的对象是自己声明属性的管理上下文对象)
注意:我们在使用时一个数据库一个模型文件,两个数据库两个模型文件,一个数据库对应一个上下文,这样可避免数据量大时,多表关联时,出现混乱.