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 就是把使用到的四个常见基本的类封装起来:NSManagedObjectModel
、NSPersistentStore
、NSPersistentStoreCoordinator
和 NSManagedObjectContext
。
创建: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]
}()
}
第二步给类添加懒加载的三个属性 NSManagedObjectContext
、NSPersistentStoreCoordinator
和NSManagedObjectModel
:
//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 获取。
而所有的NSManagedObjectModel
和NSPersistentStore
都可以通过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
方法,这里就是在applicationDidEnterBackground
和applicationWillTerminate
代理方法中调用:
coreDataStack.saveContent()
到这里,一个CoreData的栈类就创建完成了,并且已经实现了在应用退出的时候对 Context 进行 saveContent 的操作