coredata是对sqlite的封装,提供ORM机制,可以直接把oc对象保存到数据库,简单,高效,适合操作大批量数据的存储和查询,是最合适的数据管理方式
ORM:就是coreData提供的oc对象和数据的映射关系的功能。 可以把oc对象转化数据保存sqlite数据库中,也可以把从sqlite获取的数据转化为oc对象。
PersistentObjectStore:PS,存储持久对象的数据库(例如SQLite,注意CoreData也支持其他 类型的数据存储,例如xml、二进制数据等)。
PersistentStoreCoordinator 持久化存储助理,对象模型和实体类之间的转化协调器,用于管理不同存储对象的上下文
ManagedObjectContext:对象管理上下文,负责实体对象和数据库之间的交互。比如插入,删除,查询,
ManagedObjectModel:被管理的数据对象模型,对应Xcode中创建的模型文件,用来读取app中的所有数据实体
NSEntityDescription:数据实体的描述,相当于数据库的一个表,描述实体间的关系
最底层是PersistentObjectStore, ManagedObjectModel: 就是数据转为成对象的模板
在使用coredata 保存数据的过程中,我们使用NSManagetObjectContext 来对数据进行读写操作,为了提供效率,一般会使用两个context,一个context在主线程负责与UI的交互,一个context在子线程负责数据的读写,这样就很有可能造成数据的不同步。所以说coredata是多线程是不安全的
方式1 两个context 使用同一个持久化存储助理psc 。一个context处理完数据后通过通知的方式通知 另一个context 调用mergeChangeFromContextDidSavaNotification来自动同步数据 (需实践)
方式2: 给context 设置parentContext 一个parentContext 可以有多个childContext。而childContext的没有实际的psc指针 ,所以childcontext的save操作实际上只是同操作push给parentContext来完成真正的save操作,这样就实现了数据同步,这也是coredata 两层,三层结构的原理
数据冲突,只多个context的方法,不同的context的fetch操作(主要指修改和删除)对同一个managerobject进行了不同的修改,从而导致的数据数据冲突,会让两个context都保存失败。
数据冲突产生的原因: context的fetch会对会对持久化操作处理ps里的状态进行快照,保存时会让快照和ps当前的状态就行对比,如果不一致,说明用户进行了修改,但如果这个修改不是当前context的操作,会导致context的状态不连续,从而无法保存
数据冲突使用合并策略解决 1.NSErrorMergePolicy 什么也不做,但会返回错误信息 2。NSMergeByPropertyStoreTrumpMergePolicy优先使用ps的快照(即使用本地数据库) 3。NSMergeByPropertyObjectTrumpMergePolicy 使用准备保存的context的内容 4.NSOverWriteMergePolicy:准备保存的context覆盖ps快照(本地数据库部分) 5.NSRollBackMergePolicy 回滚,放弃修改,直接使用本地数据库进行版本替换
1 主线程context的类型采用NSMainQueueConcurrentcyType 2,子线程context的类型采用NSPrivateQueueConCurrentcyType。这样context会自动放入子线程中
1.context的performBlock是自动异步操作
2.context的performBlockAndWait是同步执行
3.ios10中的NSManagerObjectContext(管理上下问)从NSPersistentCotainer的viewContext获取,无需手动创建 4.ios8之后NSManageObject subclass实体类的创建时需要在右侧将实体的Codegen改为Manage/None
使用Sqlite的时候遇到过思索,当时项目没有使用FMDB,是自己直接使用sql语句实现数学库的增删改查,而且当前的情况是开发环境正常,发布的包才会出问题,最后通过debug 打印日志知道是“数据库文件被锁,无法访问”的错误,通过使用FMDB来操作数据库解决了问题,
后期通过学习FMDB指导,解决问题的根本原因是FMDB全局使用唯一FMDataBaseQueue,内部维护一个串行队列来控制app对数据库的访问,也就是说app只有dbqueue对象来操作数据库,所有的操作到都是在子线程中串行执行,自然不会死锁
多条线程同时操作同一数据库,容易造成死锁。系统崩溃 解决方案:使用串行模式操作数据库,即使用单利的方式操作数据库,比如FMDB就是这种原理