2 // CoreDataManager.swift
5 // Created by Hori,Masaki on 2017/10/26.
6 // Copyright © 2017年 Hori,Masaki. All rights reserved.
11 enum CoreDataManagerType {
17 enum CoreDataError: Error {
19 case saveLocationIsUnuseable
20 case couldNotCreateModel
21 case couldNotCreateCoordinator(String)
22 case couldNotSave(String)
25 protocol CoreDataProvider {
27 init(type: CoreDataManagerType)
29 static var core: CoreDataCore { get }
31 var context: NSManagedObjectContext { get }
33 func save(errorHandler: (Error) -> Void)
38 protocol CoreDataAccessor: CoreDataProvider {
40 func insertNewObject<T>(for entity: Entity<T>) -> T?
41 func delete(_ object: NSManagedObject)
42 func object<T>(of entity: Entity<T>, with objectId: NSManagedObjectID) -> T?
43 func objects<T>(of entity: Entity<T>, sortDescriptors: [NSSortDescriptor]?, predicate: NSPredicate?) throws -> [T]
45 func object(with objectId: NSManagedObjectID) -> NSManagedObject
48 protocol CoreDataManager: CoreDataAccessor {
50 associatedtype InstanceType = Self
52 static var `default`: InstanceType { get }
54 static func oneTimeEditor() -> InstanceType
58 extension CoreDataProvider {
60 static func context(for type: CoreDataManagerType) -> NSManagedObjectContext {
63 case .reader: return core.parentContext
65 case .editor: return core.editorContext()
69 func save(errorHandler: (Error) -> Void) {
83 guard context.commitEditing() else {
85 throw CoreDataError.couldNotSave("\(String(describing: type(of: self))) unable to commit editing before saveing")
92 } catch (let error as NSError) {
94 throw CoreDataError.couldNotSave(error.localizedDescription)
97 guard let parent = context.parent else { return }
99 // save parent context
100 var catchedError: NSError? = nil
101 parent.performAndWait {
107 } catch (let error as NSError) {
113 if let error = catchedError {
115 throw CoreDataError.couldNotSave(error.localizedDescription)
120 func removeDataFile() {
122 MOCGenerator(type(of: self).core.config).removeDataFile()
125 func presentOnMainThread(_ error: Error) {
127 if Thread.isMainThread {
129 NSApp.presentError(error)
133 DispatchQueue.main.sync {
135 _ = NSApp.presentError(error)
141 extension CoreDataAccessor {
143 func insertNewObject<T>(for entity: Entity<T>) -> T? {
145 return NSEntityDescription.insertNewObject(forEntityName: entity.name, into: context) as? T
148 func delete(_ object: NSManagedObject) {
150 context.delete(object)
153 func object<T>(of entity: Entity<T>, with objectId: NSManagedObjectID) -> T? {
155 return context.object(with: objectId) as? T
158 func objects<T>(of entity: Entity<T>, sortDescriptors: [NSSortDescriptor]? = nil, predicate: NSPredicate? = nil) throws -> [T] {
160 let req = NSFetchRequest<T>(entityName: entity.name)
161 req.sortDescriptors = sortDescriptors
162 req.predicate = predicate
164 return try context.fetch(req)
167 func object(with objectId: NSManagedObjectID) -> NSManagedObject {
169 return context.object(with: objectId)