OSDN Git Service

CoreData関連を変更
authormasakih <masakih@users.sourceforge.jp>
Sat, 28 Oct 2017 08:41:03 +0000 (17:41 +0900)
committermasakih <masakih@users.sourceforge.jp>
Sat, 28 Oct 2017 08:41:03 +0000 (17:41 +0900)
MOCGeneratorクラスを作成
例外の扱いを変更

14 files changed:
KCD/BookmarkDataStore.swift
KCD/BookmarkListViewController.swift
KCD/BookmarkManager.swift
KCD/CoreDataCore.swift
KCD/CoreDataManager.swift
KCD/GuardShelterCommand.swift
KCD/HistoryTableViewController.swift
KCD/JSONMapper.swift
KCD/LocalDataStore.swift
KCD/ManagedObjectContextGenerator.swift
KCD/MapInfoCommand.swift
KCD/ResourceHistoryDataStore.swift
KCD/ServerDataStore.swift
KCD/TemporaryDataStore.swift

index ad5f9a5..3e25b81 100644 (file)
@@ -26,7 +26,7 @@ final class BookmarkDataStore: CoreDataManager {
     
     deinit {
         
-        save()
+        save(errorHandler: presentOnMainThread)
     }
     
     let context: NSManagedObjectContext
index bfb377f..35084af 100644 (file)
@@ -159,7 +159,7 @@ extension BookmarkListViewController: NSTableViewDelegate, NSTableViewDataSource
             bookmark.order = targetOrder + $0.offset + 1
         }
         
-        store.save()
+        store.save(errorHandler: store.presentOnMainThread)
         bookmarkController.rearrangeObjects()
         reorderingBoolmarks()
         bookmarkController.rearrangeObjects()
index 5fcb010..dba1507 100644 (file)
@@ -70,7 +70,7 @@ final class BookmarkManager: NSObject, NSMenuDelegate {
         
         DispatchQueue.main.asyncAfter(deadline: .now()) {
             
-            self.editorStore.save()
+            self.editorStore.save(errorHandler: self.editorStore.presentOnMainThread)
         }
         
         return new
index c700d68..d5e710f 100644 (file)
@@ -48,7 +48,8 @@ struct CoreDataCore {
         
         do {
             
-            (model, coordinator, parentContext) = try genarate(config)
+            let generator = MOCGenerator(config)
+            (model, coordinator, parentContext) = try generator.genarate()
             
         } catch {
             
index 3fcf333..9ca4be7 100644 (file)
@@ -16,9 +16,10 @@ enum CoreDataManagerType {
 
 enum CoreDataError: Error {
     
-    case applicationDirectoryIsFile
+    case saveLocationIsUnuseable
     case couldNotCreateModel
     case couldNotCreateCoordinator(String)
+    case couldNotSave(String)
 }
 
 protocol CoreDataProvider {
@@ -29,7 +30,8 @@ protocol CoreDataProvider {
     
     var context: NSManagedObjectContext { get }
     
-    func save()
+    func save(errorHandler: (Error) -> Void)
+    func save() throws
     func removeDataFile()
 }
 
@@ -55,45 +57,72 @@ protocol CoreDataManager: CoreDataAccessor {
 // MARK: - Extension
 extension CoreDataProvider {
     
-    func save() {
+    static func context(for type: CoreDataManagerType) -> NSManagedObjectContext {
+        
+        switch type {
+        case .reader: return core.parentContext
+            
+        case .editor: return core.editorContext()
+        }
+    }
+    
+    func save(errorHandler: (Error) -> Void) {
         
-        if !context.commitEditing() {
+        do {
+            
+            try save()
             
-            print("\(String(describing: type(of: self))) unable to commit editing before saveing")
+        } catch {
             
-            return
+            errorHandler(error)
+        }
+    }
+    
+    func save() throws {
+        
+        guard context.commitEditing() else {
+            
+            throw CoreDataError.couldNotSave("\(String(describing: type(of: self))) unable to commit editing before saveing")
         }
         
         do {
             
             try context.save()
             
-        } catch {
+        } catch (let error as NSError) {
             
-            presentOnMainThread(error)
+            throw CoreDataError.couldNotSave(error.localizedDescription)
         }
         
-        if let p = context.parent {
+        guard let parent = context.parent else { return }
+        
+        // save parent context
+        var catchedError: NSError? = nil
+        parent.performAndWait {
             
-            p.performAndWait {
-                do {
-                    
-                    try p.save()
-                    
-                } catch {
-                    
-                    self.presentOnMainThread(error)
-                }
+            do {
+                
+                try parent.save()
+                
+            } catch (let error as NSError) {
+                
+                catchedError = error
             }
         }
+        
+        if let error = catchedError {
+            
+            throw CoreDataError.couldNotSave(error.localizedDescription)
+            
+        }
     }
     
     func removeDataFile() {
         
-        removeAllDataFile(named: type(of: self).core.config.fileName)
+        MOCGenerator.removeDataFile(type(of: self).core.config)
     }
     
-    private func presentOnMainThread(_ error: Error) {
+    func presentOnMainThread(_ error: Error) {
         
         if Thread.isMainThread {
             
@@ -107,15 +136,6 @@ extension CoreDataProvider {
             }
         }
     }
-    
-    static func context(for type: CoreDataManagerType) -> NSManagedObjectContext {
-        
-        switch type {
-        case .reader: return core.parentContext
-            
-        case .editor: return core.editorContext()
-        }
-    }
 }
 
 extension CoreDataAccessor {
index 2ec2c96..207b96f 100644 (file)
@@ -110,7 +110,7 @@ final class GuardShelterCommand: JSONCommand {
         let store = TemporaryDataStore.oneTimeEditor()
         
         store.notEnsuredGuardEscaped().forEach(store.delete)
-        store.save()
+        store.save(errorHandler: store.presentOnMainThread)
         Thread.sleep(forTimeInterval: 0.1)
         notify()
     }
@@ -120,7 +120,7 @@ final class GuardShelterCommand: JSONCommand {
         let store = TemporaryDataStore.oneTimeEditor()
         
         store.guardEscaped().forEach(store.delete)
-        store.save()
+        store.save(errorHandler: store.presentOnMainThread)
         Thread.sleep(forTimeInterval: 0.1)
         notify()
     }
@@ -130,7 +130,7 @@ final class GuardShelterCommand: JSONCommand {
         let store = TemporaryDataStore.oneTimeEditor()
         
         store.guardEscaped().forEach { $0.ensured = true }
-        store.save()
+        store.save(errorHandler: store.presentOnMainThread)
         Thread.sleep(forTimeInterval: 0.1)
         notify()
     }
index efacaf7..bccfa53 100644 (file)
@@ -78,7 +78,7 @@ class HistoryTableViewController: NSViewController {
             history.mark = !history.mark
         }
         
-        store.save()
+        store.save(errorHandler: store.presentOnMainThread)
     }
     
     override func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
index 6035746..a566537 100644 (file)
@@ -175,7 +175,7 @@ extension JSONMapper {
         }
         
         finishOperating()
-        store.save()
+        store.save(errorHandler: store.presentOnMainThread)
     }
     
     func beginRegister(_ object: ObjectType) {}
index 44bffee..5fba7bb 100644 (file)
@@ -26,7 +26,7 @@ final class LocalDataStore: CoreDataManager {
     
     deinit {
         
-        save()
+        save(errorHandler: presentOnMainThread)
     }
     
     let context: NSManagedObjectContext
index c77d3fb..cab2ba6 100644 (file)
 
 import Cocoa
 
-func genarate(_ config: CoreDataConfiguration) throws -> (model: NSManagedObjectModel, coordinator: NSPersistentStoreCoordinator, moc: NSManagedObjectContext) {
+final class MOCGenerator {
     
-    let model = try createModel(config)
-    let coordinator = try getCoordinator(config, model)
-    let moc = createContext(coordinator)
+    let config: CoreDataConfiguration
     
-    return (model: model, coordinator: coordinator, moc: moc)
-}
-
-func removeAllDataFile(named name: String) {
-    
-    ["", "-wal", "-shm"]
-        .map { name + $0 }
-        .map(ApplicationDirecrories.support.appendingPathComponent)
-        .forEach(removeDataFile)
-}
-
-private func removeDataFile(at url: URL) {
+    init(_ config: CoreDataConfiguration) {
+        
+        self.config = config
+    }
     
-    do {
+    func genarate() throws -> (model: NSManagedObjectModel, coordinator: NSPersistentStoreCoordinator, moc: NSManagedObjectContext) {
         
-        try FileManager.default.removeItem(at: url)
+        let model = try createModel()
+        let coordinator = try createCoordinator(model)
+        let moc = createContext(coordinator)
         
-    } catch {
+        return (model: model, coordinator: coordinator, moc: moc)
+    }
+    
+    static func removeDataFile(_ config: CoreDataConfiguration) {
         
-        print("Could not remove file for URL (\(url))")
+        ["", "-wal", "-shm"]
+            .map { config.fileName + $0 }
+            .map(ApplicationDirecrories.support.appendingPathComponent)
+            .forEach(removeFile)
     }
-}
-
-// MARK: - NSManagedObjectContext and ...
-private  func createModel(_ config: CoreDataConfiguration) throws -> NSManagedObjectModel {
     
-    guard let modelURL = Bundle.main.url(forResource: config.modelName, withExtension: "momd"),
-        let model = NSManagedObjectModel(contentsOf: modelURL) else {
+    private static func removeFile(at url: URL) {
+        
+        do {
+            
+            try FileManager.default.removeItem(at: url)
             
-            throw CoreDataError.couldNotCreateModel
+        } catch {
+            
+            print("Could not remove file for URL (\(url))")
+        }
     }
     
-    return model
-}
-
-private func getCoordinator(_ config: CoreDataConfiguration, _ model: NSManagedObjectModel) throws -> NSPersistentStoreCoordinator {
-    
-    do {
+    // MARK: - NSManagedObjectContext and ...
+    private func createModel() throws -> NSManagedObjectModel {
+        
+        guard let modelURL = Bundle.main.url(forResource: config.modelName, withExtension: "momd"),
+            let model = NSManagedObjectModel(contentsOf: modelURL) else {
+                
+                throw CoreDataError.couldNotCreateModel
+        }
         
-        return try createCoordinator(config, model)
+        return model
+    }
+    
+    private func createCoordinator(_ model: NSManagedObjectModel) throws -> NSPersistentStoreCoordinator {
         
-    } catch (let error as NSError) {
+        if !checkDirectory(ApplicationDirecrories.support) {
+            
+            throw CoreDataError.saveLocationIsUnuseable
+        }
         
-        // Data Modelが更新されていたらストアファイルを削除してもう一度
-        if error.domain == NSCocoaErrorDomain,
-            (error.code == 134130 || error.code == 134110),
-            config.tryRemake {
+        do {
             
-            removeAllDataFile(named: config.fileName)
+            return try makeCoordinator(model)
             
-            do {
-                
-                return try createCoordinator(config, model)
+        } catch (let error as NSError) {
+            
+            // Data Modelが更新されていたらストアファイルを削除してもう一度
+            if error.domain == NSCocoaErrorDomain,
+                (error.code == 134130 || error.code == 134110),
+                config.tryRemake {
                 
-            } catch {
+                MOCGenerator.removeDataFile(config)
                 
-                print("Fail to create NSPersistentStoreCoordinator twice.")
+                do {
+                    
+                    return try makeCoordinator(model)
+                    
+                } catch {
+                    
+                    print("Fail to create NSPersistentStoreCoordinator twice.")
+                }
             }
+            
+            throw CoreDataError.couldNotCreateCoordinator(error.localizedDescription)
         }
-        
-        throw error
     }
-}
-
-private func createCoordinator(_ config: CoreDataConfiguration, _ model: NSManagedObjectModel) throws -> NSPersistentStoreCoordinator {
     
-    if !checkDirectory(ApplicationDirecrories.support) {
+    private func makeCoordinator(_ model: NSManagedObjectModel) throws -> NSPersistentStoreCoordinator {
         
-        let failureReason = "Can not use directory \(ApplicationDirecrories.support.path)"
+        let coordinator: NSPersistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: model)
+        let url = ApplicationDirecrories.support.appendingPathComponent(config.fileName)
+        try coordinator.addPersistentStore(ofType: config.type,
+                                           configurationName: nil,
+                                           at: url,
+                                           options: config.options)
         
-        throw CoreDataError.couldNotCreateCoordinator(failureReason)
+        return coordinator
     }
     
-    let coordinator: NSPersistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: model)
-    let url = ApplicationDirecrories.support.appendingPathComponent(config.fileName)
-    
-    try coordinator.addPersistentStore(ofType: config.type,
-                                       configurationName: nil,
-                                       at: url,
-                                       options: config.options)
-    
-    return coordinator
-}
-
-private func createContext(_ coordinator: NSPersistentStoreCoordinator) -> NSManagedObjectContext {
-    
-    let moc = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
-    moc.persistentStoreCoordinator = coordinator
-    moc.undoManager = nil
-    
-    return moc
+    private func createContext(_ coordinator: NSPersistentStoreCoordinator) -> NSManagedObjectContext {
+        
+        let moc = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
+        moc.persistentStoreCoordinator = coordinator
+        moc.undoManager = nil
+        
+        return moc
+    }
 }
index 60c0fd3..e67a7dd 100644 (file)
@@ -22,7 +22,7 @@ final class MapInfoCommand: JSONCommand {
         let store = ServerDataStore.oneTimeEditor()
         
         store.airBases().forEach(store.delete)
-        store.save()
+        store.save(errorHandler: store.presentOnMainThread)
         
         AirBaseMapper(apiResponse).commit()
     }
index fa25b5a..db271e3 100644 (file)
@@ -26,7 +26,7 @@ final class ResourceHistoryDataStore: CoreDataManager {
     
     deinit {
         
-        save()
+        save(errorHandler: presentOnMainThread)
     }
     
     let context: NSManagedObjectContext
index 275a0d1..0b34a89 100644 (file)
@@ -26,7 +26,7 @@ final class ServerDataStore: CoreDataManager {
     
     deinit {
         
-        save()
+        save(errorHandler: presentOnMainThread)
     }
     
     let context: NSManagedObjectContext
index ec6a1b4..8d2a30f 100644 (file)
@@ -29,7 +29,7 @@ final class TemporaryDataStore: CoreDataManager {
     
     deinit {
         
-        save()
+        save(errorHandler: presentOnMainThread)
     }
     
     let context: NSManagedObjectContext