2 // CoreDataManager.swift
5 // Created by Hori,Masaki on 2017/02/05.
6 // Copyright © 2017年 Hori,Masaki. All rights reserved.
12 enum CoreDataManagerType {
18 struct CoreDataConfiguration {
21 let options: [AnyHashable: Any]
25 private static let defaultOptions: [AnyHashable: Any] = [
26 NSMigratePersistentStoresAutomaticallyOption: true,
27 NSInferMappingModelAutomaticallyOption: true
30 init(_ modelName: String,
31 fileName: String? = nil,
32 options: [AnyHashable: Any] = defaultOptions,
33 type: String = NSSQLiteStoreType,
34 tryRemake: Bool = false) {
35 self.modelName = modelName
36 self.fileName = fileName ?? "\(modelName).storedata"
37 self.options = options
39 self.tryRemake = tryRemake
44 let config: CoreDataConfiguration
45 let parentContext: NSManagedObjectContext
46 private let model: NSManagedObjectModel
47 private let coordinator: NSPersistentStoreCoordinator
49 init(_ config: CoreDataConfiguration) {
52 (model, coordinator, parentContext) = try genarate(config)
54 NSApplication.shared().presentError(error)
55 fatalError("CoreDataCore: can not initialize. \(error)")
59 func editorContext() -> NSManagedObjectContext {
60 let moc = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
61 moc.parent = parentContext
68 protocol CoreDataProvider {
69 init(type: CoreDataManagerType)
70 static var core: CoreDataCore { get }
71 var context: NSManagedObjectContext { get }
76 protocol CoreDataAccessor: CoreDataProvider {
77 func insertNewObject<T>(for entity: Entity<T>) -> T?
78 func delete(_ object: NSManagedObject)
79 func object(with objectId: NSManagedObjectID) -> NSManagedObject
80 func objects<T>(with entity: Entity<T>, sortDescriptors: [NSSortDescriptor]?, predicate: NSPredicate?) throws -> [T]
83 protocol CoreDataManager {
84 associatedtype InstanceType = Self
86 static var `default`: InstanceType { get }
87 static func oneTimeEditor() -> InstanceType
91 extension CoreDataProvider {
93 if !context.commitEditing() {
94 print("\(String(describing: type(of: self))) unable to commit editing before saveing")
99 } catch { presentOnMainThread(error) }
100 if let p = context.parent {
105 self.presentOnMainThread(error)
110 func removeDataFile() {
111 remove(name: type(of: self).core.config.fileName)
113 private func presentOnMainThread(_ error: Error) {
114 if Thread.isMainThread {
115 NSApp.presentError(error)
117 DispatchQueue.main.sync {
118 let _ = NSApp.presentError(error)
123 static func context(for type: CoreDataManagerType) -> NSManagedObjectContext {
126 return core.parentContext
128 return core.editorContext()
133 extension CoreDataAccessor {
134 func insertNewObject<T>(for entity: Entity<T>) -> T? {
135 return NSEntityDescription.insertNewObject(forEntityName: entity.name, into: context) as? T
137 func delete(_ object: NSManagedObject) {
138 context.delete(object)
140 func object(with objectId: NSManagedObjectID) -> NSManagedObject {
141 return context.object(with: objectId)
143 func objects<T>(with entity: Entity<T>,
144 sortDescriptors: [NSSortDescriptor]? = nil,
145 predicate: NSPredicate? = nil) throws -> [T] {
146 let req = NSFetchRequest<T>(entityName: entity.name)
147 req.sortDescriptors = sortDescriptors
148 req.predicate = predicate
149 return try context.fetch(req)