我设计了一个基于this blog post的核心数据堆栈(在Swift中),我有两个NSManagedObjectContext
个实例,一个主队列上下文(NSMainQueueConcurrencyType
)和一个私有队列上下文(NSPrivateQueueConcurrencyType
)其中主要上下文的工作是处理与用户交互相关的所有事情(编辑,向用户呈现数据)和私有上下文的唯一工作是写入磁盘
为了尽可能简化管理堆栈,我已经整合了Magical Record,Overcoat和Mantle。我把所有这些分成了两个类,一个是Core Data单例堆栈(基于Magical Record构建)和一个网络管理器单例(Built on Overcoat,而后者又建立在Mantle上)。
核心数据堆栈如下所示:
import UIKit
import CoreData
import MagicalRecord
class CoreData: NSObject {
enum StackType: Int {
case Default, AutoMigrating, iCloud, inMemory
}
static let sharedStack = CoreData()
private override init() {}
var type: StackType = .Default
func setupStackWithType(type: StackType, withName name: String = MagicalRecord.defaultStoreName()) {
self.type = type
switch self.type {
case .Default:
MagicalRecord.setupCoreDataStackWithStoreNamed(name)
case .AutoMigrating:
MagicalRecord.setupCoreDataStackWithAutoMigratingSqliteStoreNamed(name)
case .iCloud:
if let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first {
let url = NSURL(fileURLWithPath: documentsPath)
MagicalRecord.setupCoreDataStackWithiCloudContainer(name, localStoreAtURL: url)
} else {
print("Error: could not find documents directory")
}
case .inMemory:
MagicalRecord.setupCoreDataStackWithInMemoryStore()
}
}
func setupStackWithStoreName(storeName: String, automigrating: Bool = true) {
if automigrating {
MagicalRecord.setupCoreDataStackWithAutoMigratingSqliteStoreNamed(storeName)
} else {
MagicalRecord.setupAutoMigratingCoreDataStack()
}
}
func saveWithBlock(block: (NSManagedObjectContext!) -> ()) {
MagicalRecord.saveWithBlock(block, completion: {
(success, error) in
})
}
func cleanUp() {
MagicalRecord.cleanUp()
}
var managedObjectContext: NSManagedObjectContext {
return NSManagedObjectContext.MR_defaultContext()
}
var privateContext: NSManagedObjectContext {
return NSManagedObjectContext.MR_rootSavingContext()
}
var coordinator: NSPersistentStoreCoordinator {
return NSPersistentStoreCoordinator.MR_defaultStoreCoordinator()
}
var persistentStore: NSPersistentStore {
return NSPersistentStore.MR_defaultPersistentStore()
}
}
我的网络管理员看起来像:
import UIKit
import Overcoat
import MTLManagedObjectAdapter
class NetworkManager: OVCManagedHTTPSessionManager {
static let singleton = NetworkManager(baseURL: NSURL(string: Config.ServerBaseEndpoint), managedObjectContext: nil, sessionConfiguration: {
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
config.timeoutIntervalForRequest = 15
config.timeoutIntervalForResource = 15
return config
}())
private override init(baseURL url: NSURL?, managedObjectContext context: NSManagedObjectContext?, sessionConfiguration configuration: NSURLSessionConfiguration?) {
super.init(baseURL: url, managedObjectContext: context, sessionConfiguration: configuration)
self.responseSerializer.acceptableContentTypes = ["text/html", "application/json", "application/xml", "image/png"]
self.securityPolicy = AFSecurityPolicy(pinningMode: .None)
self.securityPolicy.allowInvalidCertificates = true
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
// MARK: - OVCHTTPSessionManager
override class func modelClassesByResourcePath() -> [String: AnyClass] {
return [Types.RestApi.Post.rawValue:Post.self, "\(Types.RestApi.Post.rawValue)/*": Post.self]
}
}
我能够完全理解的是:1)这两个类如何协同工作; 2)关于核心数据堆栈,哪个上下文要保存,哪些工作在哪个上下文等等。
对于NetworkManager.swift
(需要NSManagedObjectContext
来保留模型):
我用哪个上下文初始化管理器?我的假设是,如果您发出网络请求并且JSON被转换为中间Mantle
模型并从那里转换为NSManagedObejct
个实例,那么这些实例应该保存在专用队列上下文中,绕过主队列在这种情况下完全是上下文。
在谈论CoreData.swift
:
1)Magical Record有saveWithBlock
方法,它创建一个本地上下文并将其传播到根上下文(在这种情况下,根上下文是私有队列上下文)但是它不清楚是在街区内应该做些什么工作。
在他们的文档中,他们给出了这个例子:
Person *person = ...;
[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext){
Person *localPerson = [person MR_inContext:localContext];
localPerson.firstName = @"John";
localPerson.lastName = @"Appleseed";
}];
他们在保存块之外创建一个Person
对象,然后在本地上下文中重新创建实体,然后编辑它的属性。但是在我的情况下,所有Person
个对象都是MTLModel
的实例,而不是NSManagedObject
。当我创建一些模型对象时,因为它不是核心数据对象,所以在我使用MTLManagedObjectAdapter
将模型转换为NSManagedObject
之前,它不会被插入到任何类型的上下文中实例
最好的方法是创建MTLModel
实例,进行任何需要的编辑,然后1)在saveWithBlock
内插入新创建的托管对象本地上下文,让它传播或2)将对象插入私有队列上下文并保存。
2)我是否真的需要使用主队列上下文来保存和编辑?正如我之前所说,Mantle将模型类作为MTLModel
的子类,然后将它们映射到NSManagedObject
实例,因此我可以直接保存到私有队列上下文(其唯一的工作是无论如何要写入磁盘)
3)如果我不需要使用主队列上下文进行保存/编辑,则不会成为我用于获取NSManagedObjects
的上下文(假设私有队列&#39) ; s的工作是写入磁盘,主要队列上下文的保存/编辑功能似乎被Mantle的中间模型结构淘汰了?