CoreData (表结构变化处理)
引言:
Core Data 是 iOS 3.0 以后引入的数据持久化解决方案,其原理是对SQLite的封装,是开发者不需要接触SQL语句,就可以对数据库进行的操作.
其编码方式和原理结构方面较为特殊,本博文主要介绍在使用Core Data时遇到的各种问题以及对其核心原理进行解释.
参考资料:
1: iOS教程:Core Data数据持久性存储基础教程
http://www.dasheyin.com/ios_jiao_cheng_core_data_shu_ju_chi_jiu_xing_cun_chu_ji_chu_jiao_cheng.html
安装:
安装的方式只有一步,引入CoreData.framework 即可.
使用:
使用Core Data起步最先要了解和熟悉的类是以下三个:
1:NSManagedObjectModel
2:NSPersistentStoreCoordinator
3:NSManagedObjectContext
在此也特别的说明一下,如果你没有理解透这三个类分别是做什么的,那么往后看到的代码都有一种非常迷茫的感觉:
接下来分别介绍每一个类的具体功能和用途:
1.NSManagedObjectModel(管理对象模型,以下简称:上下文):
构建整个数据库的表结构,表字段类型,表与表之间的关系(Relationship)等等凡是和数据结构有关的定义都通过此类来管理.
那么使用此类需要一个Data Model(数据模型)文件来配合其一起使用,如下图所示新建出来:
那么我们所有数据结构的定义和设计都用这个Data Model来完成.
在代码方面需要通过文件路径的方式找到它,并初始化NSManagedObjectModel
- NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"Data Model Name" withExtension:@"momd"];
- self.keyManagedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
注:新建Data Model文件以后的文件扩展名称是: Data Model Name.xcdatamodeld但通过XCode编译打包成App以后,其会被转换成一个Data Model Name.momd文件.而我们真正要加的模型文件就是这个Data Model Name.momd文件.
2.NSPersistentStoreCoordinator(持久性数据协调器):
NSPersistentStoreCoordinator是真正意义上和SQLite打交道的类,主要根据NSManagedObjectModel 执行表结构的建立,通过NSManagedObjectContext 的命令执行数据交互 .
- self.keyPersistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: self.keyManagedObjectModel];
- // handle db upgrade
- NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
- [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
- [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,
- nil];
- if (![self.keyPersistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error])
- {}
注:通过NSManagedObjectModel初始化,一旦初始化成功,SQLite的DB,就已经有了完善的表结构关系,不过这不是我们关心的重点,继续往下.
3.NSManagedObjectContext(管理对象上下文)
NSManagedObjectContext是我们在开发中主要交互的类,数据的增删改查都通过上下文去触发命令并返回结果. 根据一个NSPersistentStoreCoordinator 完成初始化
- self.keyManagedObjectContext = [[NSManagedObjectContext alloc] init];
- [self.keyManagedObjectContext setPersistentStoreCoordinator:self.keyPersistentStoreCoordinator];
到此,CoreData的准备工作已经完成,其实XCode已经有模版可以直接完成CoreData的准备工作,不过对于新手来说,最好还是一步一步来,加以理解,以便出现BUG时,能够及时找到解决方案,贵在理解!
接下来,开始操纵数据!
插入一条?更新一条?删除一条?
熟悉Sql语句的同学:脑子里立刻会想到:insert into table , update table , delete table
那么在CoreData,这三项工作全部通过save函数来完成,一个函数完成三件事,CoreData这么犀利的?
NSPredicate(条件适配器)
NSPredicate主要为NSFetchRequest而服务,提供查询时的各种条件语句,方面过滤出复合业务需求的数据.
以下先列出 NSPredicate 支持的通配符
1:相等(==) 举例: field == 'value'
2:不相等(!=) 举例: field != 'value'
3:模糊(like) 举例: field like '*value*' 或者 field like '?value?' like 使用?表示一个字符,*表示多个字符
4:比较( > < <= >= ) 举例: field > 6
以上4种通配符都是字符串直接拼接即可,接下来的通配符在拼接字符串方面较为麻烦,但有相关代码可以辅助拼接.
5:范围(between) 举例: field between {"6", "10"}
可以通过如下代码拼接条件命令:
- NSArray *range = [[NSArray alloc]initWithObjects:@"6",@"10",nil];
- NSPredicate *betweenPredicate =[NSPredicate predicateWithFormat:@"field between %@", range];
- NSLog(@"%@",betweenPredicate.predicateFormat);
6:包含(in) 举例: filed IN {"value1", "value2"}
可以通过如下代码拼接条件命令:
- NSArray *choice = [[NSArray alloc]initWithObjects:@"value1",@"value2",nil];
- NSPredicate *inPredicate =[NSPredicate predicateWithFormat:@"filed in %@", choice];
- NSLog(@"%@",inPredicate.predicateFormat);
7:复合(or and not) 举例: filed == "value2" OR filed == "value3"
也可以通过如下代码拼接:
- NSPredicate *predicate1 = [NSPredicate predicateWithFormat:@"filed == 'value1' "];
- NSPredicate *predicate2 = [NSPredicate predicateWithFormat:@"filed == 'value2' "];
- NSArray *predicates = [[NSArray alloc]initWithObjects:predicate1,predicate2,nil];
- NSPredicate *andCompoundPredicate =[NSCompoundPredicate orPredicateWithSubpredicates:predicates];
在调用save 函数时我需要注意些什么?
一个对象只属于一个上下文对象,所以不同上下文管辖的对象不允许用一个上下文来调用save 方法,这只会失败,错误提示如下:
Illegal attempt to establish a relationship 'xyz' between objects in different contexts
解决办法是(参考:StackOverflow):
- NSManagedObject *book = // get a book in one MOC
- NSManagedObject *owner = // get an owner in a different MOC
- [[owner mutableSetValueForKey:@"books"] addObject:[owner managedObjectContext:objectWithID:[book objectID]]];
Persistent Store Coordinator (持久性数据协调器): 你可以将这个东西看作是数据库连接库,在这里,你将设置数据存储的名字和位置,以及数据存储的时机。
Managed Object Context (管理数据内容):你可以将这一部分看作是数据的实际内容,这也是整个数据库中对我们而言最重要的部分(这还用说),基本上,插入数据,查询数据,删除数据的工作都在这里完成。
NSFetchRequest* request = [[NSFetchRequest alloc] init];
[request setEntity:entity];[request setResultType:NSManagedObjectIDResultType];
[request setFetchBatchSize:20];
NSError* error = nil;
NSArray* items = [context executeFetchRequest:request error:&error];
for (NSManagedObjectID* objectID in items) {
NSManagedObject* object = [context objectWithID:objectID];
...}
countForFetchRequest:error
2:针对应用升级和表结构变动时 兼容旧版本的CoreData数据库解决办法.
- // handle db upgrade
- NSDictionary *options =
- [NSDictionary dictionaryWithObjectsAndKeys:
- [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
- [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,
- nil];
2:在实例化 NSManagedObjectModel 对象 需要传入模型名称,这里只要是你当初建立 CoreData管理对象时的名称即可.
- -com.apple.CoreData.SQLDebug 1
如下图所示:
3:警告和错误
CoreData (表结构变化处理)的更多相关文章
- canal同步异常:当表结构变化时,同步失败
场景 canal 同步Mysql一段时间后突然失败,报如如下错误: 2021-08-06 16:16:51.732 [MultiStageCoprocessor-Parser-Twt_instance ...
- 【CoreData】表之间的关联
这次是表之间怎么进行关联,要求如下: // 建立学生与班级表之间的联系 既然是表与表之间的关联,那肯定是要先创建表: // 1.创建模型文件 (相当于一个数据库里的表) // New File ——— ...
- BIEE从底层表结构向上更新
影响BIEE查询结果的几个因素: 1.数据库表结构变化后,RPD如何处理? 更新物理层 增加.删除.修改表名. 添加字段:右键点击连接池,点击导入元数据.勾掉关键字,重新导入那张表. 删除字段:直接右 ...
- MySQL表结构同步工具 mysql-schema-sync
mysql-schema-sync 是一款使用go开发的.跨平台的.绿色无依赖的 MySQL 表结构自动同步工具.用于将线上(其他环境)数据库结构变化同步到测试(本地)环境! 可以解决多人开发,每人都 ...
- mysql基础(一)——表、索引、视图
SQL语句不区分大小写 创建数据库 create database myData 删除数据库 drop database myData 创建表 create table company ( code ...
- 让EntityFramwork自动更新表结构
在项目开发中,难免会遇到数据库表结构变化的情况,手动去维护数据库是一件繁琐的事情.好在EntityFramwork为我们这些懒人提供了可供自动更新数据结构的机制,废话不多说,直接上代码: 首先创建一个 ...
- Oracle基础之分析表
analyze table tablename compute statistics; analyze index indexname compute statistics; (analyze 不会重 ...
- IOS CoreData的(增删查改)
(1).CoreDataa>什么是CoreDatab>CoreData增删改查 "什么时候使用COredata 什么时候使用FMDatabases"CoreData 在 ...
- MySQL进阶:约束,多表设计,多表查询,视图,数据库备份与还原
MySQL进阶 知识点梳理 一.约束 1. 外键约束 为什么要有外键约束 例如:一个user表,一个orderlist 如果现在想要直接删除id为1的张三,但是orderlist里还有用户id为1的订 ...
随机推荐
- js原型链接(二)和object类的create方法
原型链的内部执行方式 <script> function Myclass(){ this.x=" x in Myclass"; } var obj=new Myclas ...
- 为你的Windows7设置动态壁纸
From:http://www.cnblogs.com/killerlegend/p/3644014.html By KillerLegend DreamScene是Vista上的一个功能,可以让你设 ...
- Adapter的getView方法详解
来自:http://blog.csdn.net/yelbosh/article/details/7831812 BaseAdapter就Android应用程序中经常用到的基础数据适配器,它的主要用途是 ...
- Ruby on Rail学习笔记
说明:只针对Windows8.1 Windows下,上rubyinstaller上下载最新的railsinstaller包含Ruby2.1的,然后更新gem 用命令: gem update --sys ...
- gravity、layout_gravity、ayout_weight 区别及用法
layout_gravity 表示组件自身在父组件中的位置. gravity 表示组件的子组件在组件中的位置. weight 意思是权重.比重,即当前控件在画布中所占的空间 ...
- IBM MQ扩大队列最大消息长度
要设置MQ的最大消息长度,需要考虑同时设置队列管理,队列以及通道的最大消息长度. 具体操作如下: runmqsc 队列管理器名称 alter qmgr maxmsgl(10000000) 1 : al ...
- 禁用DropDownList的Items
可以先看看效果,被禁用的DropDownList的Items已经无法选取与颜色也变为灰色. 刚开始,DropDownList没有接收从网址传来的参数时,它每一个Item都是可以选取的,一旦接收了值.所 ...
- Go语言示例-函数返回多个值
Go语言中函数可以返回多个值,这和其它编程语言有很大的不同.对于有其它语言编程经验的人来说,最大的障碍不是学习这个特性,而是很难想到去使用这个特性. 简单如交换两个数值的例子: package mai ...
- Linux获取线程tid线程名
Linux获取线程tid线程名 1 2 3 4 5 6 //thread name char cThreadName[32] = {0}; prctl(PR_GET_NAME, (unsigned l ...
- 初始twisted(一)
1.与同步模型的优势: 1.有大量的任务,一个时刻内至少有一个任务要运行 2.任务执行大量的I/O,同步模型会因为任务阻塞而浪费大量时间 3.任务之间相互独立,任务内部交互少. 2.与同步模式客户端的 ...