一、多线程设计
基本是按照我的这篇文章中的第二种方案。MR提供的与每个线程绑定的ctx都是以default context为parent context的, 从而实现子线程的操作可以同步到主线程中去
二、MR中维护的MOC结构
为了方便说明,以下内容中采用简称:RSC = root saving context, DC = default context
- RSC为NSPrivateQueueConcurrencyType类型的context, 其parent store为PSC,不与任何线程绑定。
- DC 为NSMainQueueConcurrencyType类型的context, 其parent context为RSC, 与主线程绑定。
- MR为每一个线程绑定了一个NSPrivateQueueConcurrencyType类型的context, 以
MagicalRecord_NSManagedObjectContextForThreadKey
为key, ctx为value, 存储在线程的threadDictionary中。 该context以DC为parent context. - 调用"+MR_context"方法,获取一个新的,以RSC(而非DC)为parent context的PrivateQueueConcurrency类型的ctx。
三、MR中MOC之间的同步
- DC和RSC之间的同步
NSManagedObjectContext类会监听RSC抛出的NSManagedObjectContextDidSaveNotification。 当RSC完成save操作后, DC会mergeChanges进行同步。而DC以RSC为 parent context, DC做保存操作之后, 变化会自动同步到RSC中 - DC和子线程绑定的context的同步
由于子线程绑定的context以DC为parent context,因此子线程context做保存操作之后,变化会自动同步到DC中。 如果子线程绑定的context需要同步DC中的变化,则需要采用下面的第三种方式 - 主动同步:MR在MagicalObjectContext的"MagicalObserving" category中提供了接口用来做ctx之间的同步。内部的机制是通过监听
NSManagedObjectContextDidSaveNotification
通知。
四、MR的使用
- 一键setup , 初始化各个类的default变量值
[MagicalRecord setupCoreDataStack]; - 执行后台任务
直接使用MagicalRecord类提供的+ saveWithBlock:(void(^)(NSManagedObjectContext *localContext))block
方法即可。block里的操作应该使用传入的参数localContext。该localContext以RSC为parent ctx, 而不是DC。 - context的保存
MR提供了context的多种保存方式,包括指定同步还是异步,仅保存当前context还是一直保存到persistent store中。 - Active Record Pattern体现在NSManagedObject的一系列category方法中。比如:
- 增加一个对象:
- +MR_createEntity: 在当前线程绑定的ctx中增加
- +MR_createEntityInContext: 在传入的ctx中增加
- 删除一个对象:
- -MR_deleteEntity: 在receiver所属的ctx中把receiver删除
- -MR_deleteEntityInContext: 在传入的ctx中把与receiver对应的object删除
- 清空一张表:
- +MR_truncateAll: 在当前线程绑定的ctx中清空这张表
- +MR_truncateAllInContext: 在传入的ctx中清空这张表
- 查找:
体现在NSManagedObject的MagicalRequest
、MagicalAggregation
和MagicalFinders
三个categories中。譬如,- MR_findFirstInContext: 在传入的ctx中查找第一个对象
- 增加一个对象: