联合使用地幔,大衣和魔法记录的简化核心数据堆栈

时间:2015-09-26 20:38:05

标签: ios core-data magicalrecord github-mantle overcoat

我设计了一个基于this blog post的核心数据堆栈(在Swift中),我有两个NSManagedObjectContext个实例,一个主队列上下文(NSMainQueueConcurrencyType)和一个私有队列上下文(NSPrivateQueueConcurrencyType)其中主要上下文的工作是处理与用户交互相关的所有事情(编辑,向用户呈现数据)和私有上下文的唯一工作是写入磁盘

为了尽可能简化管理堆栈,我已经整合了Magical RecordOvercoatMantle。我把所有这些分成了两个类,一个是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的中间模型结构淘汰了?

0 个答案:

没有答案