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 model: NSManagedObjectModel
46 let coordinator: NSPersistentStoreCoordinator
47 let parentContext: NSManagedObjectContext
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 var core: CoreDataCore { get }
71 var context: NSManagedObjectContext { get }
75 protocol CoreDataAccessor: CoreDataProvider {
76 func insertNewObject<T>(for entity: Entity<T>) -> T?
77 func delete(_ object: NSManagedObject)
78 func object(with objectId: NSManagedObjectID) -> NSManagedObject
79 func objects<T>(with entity: Entity<T>, sortDescriptors: [NSSortDescriptor]?, predicate: NSPredicate?) throws -> [T]
82 protocol CoreDataManager {
83 associatedtype InstanceType = Self
85 static var `default`: InstanceType { get }
86 static func oneTimeEditor() -> InstanceType
92 extension CoreDataProvider {
94 if !context.commitEditing() {
95 print("\(String(describing: type(of: self))) unable to commit editing before saveing")
100 } catch { presentOnMainThread(error) }
101 if let p = context.parent {
106 self.presentOnMainThread(error)
111 private func presentOnMainThread(_ error: Error) {
112 if Thread.isMainThread {
113 NSApp.presentError(error)
115 DispatchQueue.main.sync {
116 let _ = NSApp.presentError(error)
122 extension CoreDataAccessor {
123 func insertNewObject<T>(for entity: Entity<T>) -> T? {
124 return NSEntityDescription.insertNewObject(forEntityName: entity.name, into: context) as? T
126 func delete(_ object: NSManagedObject) {
127 context.delete(object)
129 func object(with objectId: NSManagedObjectID) -> NSManagedObject {
130 return context.object(with: objectId)
132 func objects<T>(with entity: Entity<T>,
133 sortDescriptors: [NSSortDescriptor]? = nil,
134 predicate: NSPredicate? = nil) throws -> [T] {
135 let req = NSFetchRequest<T>(entityName: entity.name)
136 req.sortDescriptors = sortDescriptors
137 req.predicate = predicate
138 return try context.fetch(req)
142 extension CoreDataManager where Self: CoreDataProvider {
143 func removeDataFile() {
144 remove(name: core.config.fileName)