var context: NSManagedObjectContext { get }
- func save(errorHandler: (Error) -> Void)
- func save() throws
- func removeDataFile()
+ func save(errorHandler: @escaping (Error) -> Void)
}
protocol CoreDataAccessor: CoreDataProvider {
+ func sync(execute: () -> Void)
+ func sync<T>(execute: () -> T) -> T
+ func async(execute: @escaping () -> Void)
+
func insertNewObject<T>(for entity: Entity<T>) -> T?
func delete(_ object: NSManagedObject)
func object<T>(of entity: Entity<T>, with objectId: NSManagedObjectID) -> T?
protocol CoreDataManager: CoreDataAccessor {
- associatedtype InstanceType = Self
+ static var `default`: Self { get }
- static var `default`: InstanceType { get }
+ static func oneTimeEditor() -> Self
+}
+
+func presentOnMainThread(_ error: Error) {
- static func oneTimeEditor() -> InstanceType
+ if Thread.isMainThread {
+
+ NSApp.presentError(error)
+
+ } else {
+
+ DispatchQueue.main.sync {
+
+ _ = NSApp.presentError(error)
+ }
+ }
}
// MARK: - Extension
static func context(for type: CoreDataManagerType) -> NSManagedObjectContext {
switch type {
- case .reader: return core.parentContext
+ case .reader: return core.readerContext
case .editor: return core.editorContext()
}
}
- func save(errorHandler: (Error) -> Void) {
+ func save(errorHandler: @escaping (Error) -> Void = presentOnMainThread) {
- do {
-
- try save()
+ // parentを辿ってsaveしていく
+ func propagateSaveAsync(_ context: NSManagedObjectContext) {
- } catch {
-
- errorHandler(error)
- }
- }
-
- func save() throws {
-
- guard context.commitEditing() else {
+ guard let parent = context.parent else {
+
+ return
+ }
- throw CoreDataError.couldNotSave("\(String(describing: type(of: self))) unable to commit editing before saveing")
+ parent.perform {
+
+ do {
+
+ try parent.save()
+
+ propagateSaveAsync(parent)
+
+ } catch {
+
+ errorHandler(error)
+ }
+ }
}
- do {
+ context.performAndWait {
- try context.save()
-
- } catch (let error as NSError) {
-
- throw CoreDataError.couldNotSave(error.localizedDescription)
- }
-
- guard let parent = context.parent else { return }
-
- // save parent context
- var catchedError: NSError? = nil
- parent.performAndWait {
+ guard context.commitEditing() else {
+
+ errorHandler(CoreDataError.couldNotSave("Unable to commit editing before saveing"))
+ return
+ }
do {
- try parent.save()
+ try context.save()
+
+ // save reader and writer context async.
+ // non throw exceptions.
+ propagateSaveAsync(context)
- } catch (let error as NSError) {
+ } catch let error as NSError {
- catchedError = error
+ errorHandler(CoreDataError.couldNotSave(error.localizedDescription))
}
}
-
- if let error = catchedError {
-
- throw CoreDataError.couldNotSave(error.localizedDescription)
-
- }
}
+}
+
+extension CoreDataAccessor {
- func removeDataFile() {
+ func sync(execute work: () -> Void) {
- MOCGenerator(type(of: self).core.config).removeDataFile()
+ self.context.performAndWait(work)
}
- func presentOnMainThread(_ error: Error) {
+ func sync<T>(execute work: () -> T) -> T {
- if Thread.isMainThread {
-
- NSApp.presentError(error)
-
- } else {
-
- DispatchQueue.main.sync {
-
- _ = NSApp.presentError(error)
- }
+ var value: T!
+ sync {
+ value = work()
}
+ return value
+ }
+
+ func async(execute work: @escaping () -> Void) {
+
+ self.context.perform(work)
}
-}
-
-extension CoreDataAccessor {
func insertNewObject<T>(for entity: Entity<T>) -> T? {
req.sortDescriptors = sortDescriptors
req.predicate = predicate
- return try context.fetch(req)
+ var result: [T]?
+ var caughtError: Error?
+ sync {
+ do {
+
+ result = try self.context.fetch(req)
+ } catch {
+
+ caughtError = error
+ }
+ }
+ if let error = caughtError {
+
+ throw error
+ }
+
+ return result ?? []
}
func object(with objectId: NSManagedObjectID) -> NSManagedObject {
- return context.object(with: objectId)
+ var result: NSManagedObject?
+ sync {
+ result = self.context.object(with: objectId)
+ }
+ return result!
+ }
+}
+
+extension CoreDataManager {
+
+ static func oneTimeEditor() -> Self {
+
+ return Self.init(type: .editor)
}
}