2 // CoreDataManager.swift
5 // Created by Hori,Masaki on 2017/02/05.
6 // Copyright © 2017年 Hori,Masaki. All rights reserved.
12 enum CoreDataManagerType {
19 struct CoreDataConfiguration {
23 let options: [AnyHashable: Any]
27 private static let defaultOptions: [AnyHashable: Any] = [
28 NSMigratePersistentStoresAutomaticallyOption: true,
29 NSInferMappingModelAutomaticallyOption: true
32 init(_ modelName: String,
33 fileName: String? = nil,
34 options: [AnyHashable: Any] = defaultOptions,
35 type: String = NSSQLiteStoreType,
36 tryRemake: Bool = false) {
38 self.modelName = modelName
39 self.fileName = fileName ?? "\(modelName).storedata"
40 self.options = options
42 self.tryRemake = tryRemake
48 let config: CoreDataConfiguration
49 let parentContext: NSManagedObjectContext
50 private let model: NSManagedObjectModel
51 private let coordinator: NSPersistentStoreCoordinator
53 init(_ config: CoreDataConfiguration) {
59 (model, coordinator, parentContext) = try genarate(config)
63 NSApplication.shared.presentError(error)
64 fatalError("CoreDataCore: can not initialize. \(error)")
68 func editorContext() -> NSManagedObjectContext {
70 let moc = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
71 moc.parent = parentContext
79 protocol CoreDataProvider {
81 init(type: CoreDataManagerType)
83 static var core: CoreDataCore { get }
85 var context: NSManagedObjectContext { get }
91 protocol CoreDataAccessor: CoreDataProvider {
93 func insertNewObject<T>(for entity: Entity<T>) -> T?
94 func delete(_ object: NSManagedObject)
95 func object<T>(of entity: Entity<T>, with objectId: NSManagedObjectID) -> T?
96 func objects<T>(of entity: Entity<T>, sortDescriptors: [NSSortDescriptor]?, predicate: NSPredicate?) throws -> [T]
98 func object(with objectId: NSManagedObjectID) -> NSManagedObject
101 protocol CoreDataManager {
103 associatedtype InstanceType = Self
105 static var `default`: InstanceType { get }
107 static func oneTimeEditor() -> InstanceType
111 extension CoreDataProvider {
115 if !context.commitEditing() {
117 print("\(String(describing: type(of: self))) unable to commit editing before saveing")
128 presentOnMainThread(error)
131 if let p = context.parent {
140 self.presentOnMainThread(error)
146 func removeDataFile() {
148 remove(name: type(of: self).core.config.fileName)
151 private func presentOnMainThread(_ error: Error) {
153 if Thread.isMainThread {
155 NSApp.presentError(error)
159 DispatchQueue.main.sync {
161 _ = NSApp.presentError(error)
166 static func context(for type: CoreDataManagerType) -> NSManagedObjectContext {
170 return core.parentContext
173 return core.editorContext()
178 extension CoreDataAccessor {
180 func insertNewObject<T>(for entity: Entity<T>) -> T? {
182 return NSEntityDescription.insertNewObject(forEntityName: entity.name, into: context) as? T
185 func delete(_ object: NSManagedObject) {
187 context.delete(object)
190 func object<T>(of entity: Entity<T>, with objectId: NSManagedObjectID) -> T? {
192 return context.object(with: objectId) as? T
195 func objects<T>(of entity: Entity<T>, sortDescriptors: [NSSortDescriptor]? = nil, predicate: NSPredicate? = nil) throws -> [T] {
197 let req = NSFetchRequest<T>(entityName: entity.name)
198 req.sortDescriptors = sortDescriptors
199 req.predicate = predicate
201 return try context.fetch(req)
204 func object(with objectId: NSManagedObjectID) -> NSManagedObject {
206 return context.object(with: objectId)