创建自己的 Core Data Stack

2017年05月16日17:21:37 更新:

给一段项目中最新的实现,有时间好好修正下:


protocol UsesCoreDataObjects: class {
    var managedObjectContext: NSManagedObjectContext? { get set }
}

class CoreDataStack {
    private let modelName: String
    init(modelName: String) {
        self.modelName = modelName
    }
    
    lazy var managedContext: NSManagedObjectContext = self.storeContainer.viewContext
    var savingContext: NSManagedObjectContext {
        return storeContainer.newBackgroundContext()
    }
    
    private lazy var storeContainer: NSPersistentContainer = {
        let container = NSPersistentContainer(name: self.modelName)
        //persistentStoreDescriptions 不写的话是系统自己做,可以自己制定路径
        container.loadPersistentStores { (storeDescription, error) in
            if let error = error as NSError? {
                print("Unresolved error \(error), \(error.userInfo)")
            }
        }
        return container
    }()
    
    func saveContext () {
        guard managedContext.hasChanges else { return }
        do {
            try managedContext.save()
        } catch let error as NSError {
                print("Unresolved error \(error), \(error.userInfo)")
        }
    }
}

分割线以上是 2017年05月16日17:21:23 添加的,下面是旧的内容


简单的 Core Data Stack 就是把使用到的四个常见基本的类封装起来:NSManagedObjectModelNSPersistentStoreNSPersistentStoreCoordinatorNSManagedObjectContext

创建:CoreDataStack.swift

第一部分创建 Model 的名字和 Document 的路径URL:
创建新的 .swift 文件

import CoreData
class CoreDataStack {

  let modelName = "BALABALA"

  //Document's URL
  private lazy var applciationDocumentDirectory: NSURL = {
    let urls = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
    return urls[urls.count-1]
  }()
}

第二步给类添加懒加载的三个属性 NSManagedObjectContextNSPersistentStoreCoordinatorNSManagedObjectModel

 //NSManagedObjectContext
 //Note: ConcurrencyType 的具体参数会在后面补充添加,暂时先使用 .MainQueueConcurrencyType
 //创建出来Context是完全没有意义的,直到设置了Context的PersistentStoreCoordinator
 lazy var context: NSManagedObjectContext = {
   var managedObjectContext = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
   managedObjectContext.persistentStoreCoordinator = self.psc
   return managedObjectContext
 }()
 
 //NSPersistentStoreCoordinator
 //对StoreCoordinator做懒加载,StoreCoordinator是介与PersistentStore(s)和ObejctModel之间的,所以至少需要一个PersistentStore。
 private lazy var psc: NSPersistentStoreCoordinator = {
   //coordinator init,传入Model,Model指所有的Entity和所有的relationship
   let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
//    PersisitentStore 的物理存储路径
   let url = self.applciationDocumentDirectory.URLByAppendingPathComponent(self.modelName)
   do{
//      一些Option配置:
     let options = [NSMigratePersistentStoresAutomaticallyOption : true]
//addPersistentStoreWithType 选择一个SQLite的type,使用SQLite作为存储模式。
     try coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL:url, options: options)
   } catch {
     print("Error adding persistnet store.")
   }
   return coordinator
 }()
 
 //NSManagedObjectModel
 //这里包含着MainBundle里面的momb文件里面的 `.xcdatamodeld` 文件,就是Xcode图形化设计Entity和Relationship的那个文件,使用它来创建ManagedObjectModel
 private lazy var managedObjectModel: NSManagedObjectModel = {
   let modelURL = NSBundle.mainBundle().URLForResource(self.modelName, withExtension: "momd")!
   return NSManagedObjectModel(contentsOfURL: modelURL)!
 }()

添加的每 Property 都对应着 Core Data 的重要组件,使用Lazy Loading,每个组件都依赖其他的组件。

这些 Property 中只有NSManagedObjectContext是 Public 的 Property,其余的都是 private 修饰。private 修饰的组件外界不需要获取的。

另外,NSPersistentStoreCoordinator可以通过 NSManagedObjectContext的 Public property 获取。

而所有的NSManagedObjectModelNSPersistentStore都可以通过NSPersistentStoreCoordinator的Public property 来获取。

StoreCoordinator做懒加载,它是介与PersistentStore(s)ObejctModel之间的,所以至少需要一个PersistentStore

最后添加一个方法:

//保存的方法
func saveContent () {
  if context.hasChanges {
    do {
      try context.save()
    } catch let error as NSError {
      print("Error: \(error.localizedDescription)")
      abort()
    }
  }
}

AppDelegate中添加LazyLoading的iVar:

lazy var coreDataStack = CoreDataStack()

didFinishLaunchingWIthOption的方法中可以给rootViewController中的Context赋值了:

let navigationController = window!.rootViewController as! UINavigationController
let viewController = navigationController.topViewController as! ViewController
viewController.managedContext = coreDataStack.context

接下来在合适的时机调用SaveContent方法,这里就是在applicationDidEnterBackgroundapplicationWillTerminate代理方法中调用:

coreDataStack.saveContent()

到这里,一个CoreData的栈类就创建完成了,并且已经实现了在应用退出的时候对 Context 进行 saveContent 的操作

你可能感兴趣的:(创建自己的 Core Data Stack)