文章出处,原创于 https://HawkingOuYang.github.io/
© OYXJ
并发编程:API 及挑战
Core Data Lightweight Migration
Ref:
(1)http://www.objc.io/issue-4/core-data-migration.html
(2)http://stackoverflow.com/questions/1830079/iphone-core-data-automatic-lightweight-migration (这个好,具体到步骤)
(3)http://www.raywenderlich.com/86136/lightweight-migrations-core-data-tutorial
(4)http://www.raywenderlich.com/27657/how-to-perform-a-lightweight-core-data-migration
(7)http://stackoverflow.com/questions/2730832/how-can-i-duplicate-or-copy-a-core-data-managed-object
(8)http://stackoverflow.com/questions/3256195/how-to-deal-with-temporary-nsmanagedobject-instances
CoreData数据库轻量迁移
CoreData数据库轻量迁移,针对于同一个iOSApp在版本升级(更新安装App)的过程中,需要注意的数据库迁移;如果不进行数据库迁移,则会导致,覆盖安装闪退。这里说的数据库迁移,特指:CoreData轻量数据库迁移。
CoreData轻量数据库迁移,具体步骤如下:
iPhone Core Data “Automatic Lightweight Migration”
http://stackoverflow.com/questions/1830079/iphone-core-data-automatic-lightweight-migration
To recap/Full guide:
1、 Before making any change, create a new model version.
In Xcode 4: Select your .xcdatamodel –>> Editor –>> Add Model Version.
In Xcode 3: Design –>> Data Model –>> Add Model Version.
You will see that a new .xcdatamodel is created in your .xcdatamodeld folder (which is also created if you have none).
2、 Save.
3、 Select your new .xcdatamodel and make the change you wish to employ in accordance withthe Lightweight Migration documentation.
4、 Save.
5、 Set the current/active schema to the newly created schema.
With the .xcdatamodeld folder selected:
In Xcode 4: Utilities sidebar –>> File Inspector –>> Versioned Core Data Model –>> Select the new schema.
In Xcode 3: Design –>> Data Model –>> Set Current Version.
The green tick on the .xcdatamodel icon will move to the new schema.
6、 Save.
7、 Implement the necessary code to perform migration at runtime.
Where your NSPersistentStoreCoordinator is created (usually AppDelegate class), for the options parameter, replace nil with the following code:
|
|
8、 Run your app. If there’s no crash, you’ve probably successfully migrated :)
9、 When you have successfully migrated, the migration code (step 7) can be removed. (It is up to the developer to determine when the users of a published app can be deemed to have migrated.)
IMPORTANT: Do not delete old model versions/schemas. Core Data needs the old version to migrate to the new version.
中文如下:
1、选中DB.xcdatamodeld (对,那个绿色钩)
2、Xcode工具栏中,Editor —> Add Model Version
特别注意:先备份,再更改数据库。
v0.6.0_20150828_01.xcdatamodel
其中:v0.6.0 —> 数据库版本号
20150828 —> 日期,即哪天改动的。
01 —> 上面这个日期的第几次更改数据
表结构
一般来说:
数据表schema 由iOS开发组的一个成员来维护,以便减少 数据表schema 更改的次数。
特别来说:
对于已经上架AppStore的版本,一定要做好CoreData的数据迁移,否则在覆盖安装之后,app重新launch(启动)的时候,会闪退。
3、更改表结构,即编辑DB.xcdatamodeld文件。
特别说明:
如果 跳过第二步:2、Xcode工具栏中,Editor —> Add Model Version
直接到第三部:3、更改表结构,即编辑DB.xcdatamodeld文件。
已经导致:覆盖安装崩溃。
补救方法如下:
1、不管你是用Git还是SVN,回到你更改数据库之前的一个时间点(代码的snapshot),在那个时候备份数据模型文件(即对DB.xcdatamodeld 增加Model Version)。
2、把这个增加的Model Version,添加到现在的DB.xcdatamodeld中。
测试验证:覆盖安装,不崩溃。
CoreData使用参考
深入浅出 Cocoa 之 Core Data(1)- 框架详解
CoreData使用特别注意
1、每个NSThread实例,必须有各自的NSManagedObjectContext实例,该Context实际上是把db.sqlite文件读取到内存中(使用fault这种内存策略,建立索引,以减小内存占用)。
2、CoreData的数据库实体(即 Entity,继承自NSManagedObject),存在于各自所属NSThread实例的NSManagedObjectContext实例中,并且Entity 不能 跨线程传递;如果 一定要 跨线程 传递Entity,请传递该Entity的主键(比如 myEntity.entityUUID),然后在 另一个线程 使用 myEntity.entityUUID 从这个所谓 另一个线程 的Context,查找到这个Entity。
3、临时Entity数据,即 不打算 持久化的Entity,请使用 临时的Context,并且一定不能 [临时Context save]
4、Entity深拷贝?上面有代码。
5、CoreData 数据库迁移?CoreData 关系建立与移除?上面链接有。
CoreData多线程数据合并、多线程数据同步
|
|
业务管理类的抽象基类
|
|
自定义操作(基于:Block)
|
|
自定义操作(基于:Selector)
|
|
自定义操作队列
|
|
举个🌰(栗子 li zi ) for example
|
|
栗子 1
|
|
栗子 2
|
|
这个例子好长,来,看两张美图,放松一下😌。
栗子 3
|
|
CoreData 谓词NSPredicate
nshipster.cn NSPredicate NSPredicate是一个Foundation类,它指定数据被获取或者过滤的方式。它的查询语言就像SQL的WHERE和正则表达式的交叉一样,提供了具有表现力的,自然语言界面来定义一个集合被搜寻的逻辑条件。
NSPredicate that is the equivalent of SQL’s LIKE
Core Data, NSPredicate and to-many key (CoreData数据关系 的 谓词1)
How to correctly setup a NSPredicate for a to-many relationship when using Core Data? (CoreData数据关系 的 谓词2)
What’s better way to build NSPredicate with to-many deep relationships? (CoreData数据关系 的 谓词3)
CoreData的关系型数据
|
|
CoreData的Entity深拷贝
|
|
CoreData实体Entity深度拷贝(每一个‘字段’、每一个‘数据关系’),Context上下文 数据重复,导致PersistentStoreFile数据库重复 —> fix BUG —> 自测 通过。
|
|
entity深拷贝,举例:
|
|
|
|
CoreData的内存策略(fault)
Coredata Error “ data: fault ”
Entity不能跨线程使用(特别是修改),否则:
|
|
Coredata Error “data:
http://stackoverflow.com/questions/7304257/coredata-error-data-fault
|
|
This is expected behaviour, core data won’t return full objects until you need to access the persistent values of the objects. Each of your returned objects will be a ‘fault’ until this point.
You can force the fetch request to return full objects using [request setReturnsObjectsAsFaults:NO], but in most cases what you have will be fine. Look at the documentation for NSFetchRequest for more information.
If you access one of the properties, core data will go to the persistent store and fetch the rest of your values, then you’ll get the full description in the logs.
This seems to be such a common misunderstanding that I decided to write about it, here.
“Core Data could not fulfill a fault” for objects that were created in the appDelegate managedObjectContext on the main thread
http://stackoverflow.com/questions/20006689/core-data-could-not-fulfill-a-fault-for-objects-that-were-created-in-the-appde
|
|
上述代码
改成
更为合理。
CoreData性能优化
指定字段
数据分页
线程池中,并发数量 控制 (使用 操作队列)
在主线程操作数据库 ——> 不可避免有这样的场景,数据量很小(三五条数据)。
其他情况,批量写入数据库,都在 worker 线程。——> 这样的worker 线程,只有3个(太多导致 context增多,同时context合并数据 也耗性能)。
问题:以后数据越来越多,问题就明显了 ?——> 不会,因为:必须有一个 主线程的Context,而 Context的内存策略是 fault(这个不会 阻塞 线程 很久;如果数据量很大,使用 worker线程,不要用主线程)。
CoreData + NSFetchedResultsController
NSFetchedResultsController 通过KVO/Notification模式,在一个线程(一般是主线程) 观察CoreData的一个NSManagedObjectContext(一般是主线程的Context)的变化(增、删、改),定义一个NSFetchRequest将数据(包括数据的增删改)通过delegate模式绑定到view(一般是tableView 或 collectionView)。
具体做法,这里 Stanford公开课-iOS9-Swift-第10课 Core Data 和 这里 Stanford公开课-iOS7-ObjectiveC-第13课 Core Data and Tale View , Stanford(美国斯坦福大学)的iOS开发公开课 下载方式在这 , Stanford的官网下载代码:cs193p iPhone App Dev 和 cs193p iPhone App Dev downloads-2013-fall
做framework的脚本
|
|
CCoreData.framework + CAbstractManager.framework
基于Apple的 CoreData.framework ,根据CoreData的线程安全、多线程数据合并、数据库迁移、关系型数据 等特点,使用Objective-C,封装成为 CCoreData.framework 。
基于`工厂模式`,`单例模式`,`多线程并发` ,`通知+block 进行线程通讯`,`GCD + Operation Queue` 等,并依赖于CoreData的线程安全、多线程数据合并(即自己封装的 CCoreData.framework ),使用Objective-C,封装成为 CAbstractManager.framework 。
App Store Review 需要支持bitcode,所以自己造的framework也得支持bitcode,那么,修改工程配置的bitcode为YES,如下图:
|
|
by OYXJ thinking carefully at night on 2016.10.26, and in the morning on 2016.10.27,
resulting in a conclusion that:
change MY_THREAD_CONCURRENT_OPERATION_COUNT after —> CAbstractManager.framework is complied into “Unix executable” file named “CAbstractManager”, WON’T re-compile CAbstractManager, thus the effort of trying changing MY_THREAD_CONCURRENT_OPERATION_COUNT does not work.
so, revert back to AS IS.
|
|
|
|
|
|
Base 查看沙盒 数据库,分享一下。
踩过的坑 & Debug
CoreData 多个Context的数据同步
以下数据,已经洗白,避免泄漏公司项目的关键信息。
多线程数据同步
对比
etag
sourceID
syncStatus
|
|
|
|
|
|
|
|