OSDN Git Service

UAをVersion/10.0.3 Safari/602.4.8に変更
[kcd/KCD.git] / KCD / ManagedObjectContextGenerator.swift
1 //
2 //  ManagedObjectContextGenerator.swift
3 //  KCD
4 //
5 //  Created by Hori,Masaki on 2017/03/21.
6 //  Copyright © 2017年 Hori,Masaki. All rights reserved.
7 //
8
9 import Cocoa
10
11 enum CoreDataError: Error {
12     case applicationDirectoryIsFile
13     case couldNotCreateModel
14     case couldNotCreateCoordinator(String)
15 }
16
17 func remove(name: String) {
18     ["", "-wal", "-shm"]
19         .map { name + $0 }
20         .map { ApplicationDirecrories.support.appendingPathComponent($0) }
21         .forEach { removeDataFile(at: $0) }
22 }
23
24 func genarate(_ config: CoreDataConfiguration) throws ->
25     (model: NSManagedObjectModel, coordinator: NSPersistentStoreCoordinator, moc: NSManagedObjectContext) {
26         do {
27             let model = try createModel(config)
28             let coordinator = try getCoordinator(config, model)
29             let moc = createContext(coordinator)
30             return (model: model, coordinator: coordinator, moc: moc)
31         } catch {
32             throw error
33         }
34 }
35
36 private func removeDataFile(at url: URL) {
37     do {
38         try FileManager.default.removeItem(at: url)
39     } catch {
40         print("Could not remove file for URL (\(url))")
41     }
42 }
43
44 // MARK: - NSManagedObjectContext and ...
45 private  func createModel(_ config: CoreDataConfiguration) throws -> NSManagedObjectModel {
46     guard let modelURL = Bundle.main.url(forResource: config.modelName, withExtension: "momd"),
47         let model = NSManagedObjectModel(contentsOf: modelURL)
48         else {
49             throw CoreDataError.couldNotCreateModel
50     }
51     return model
52 }
53 private func getCoordinator(_ config: CoreDataConfiguration,
54                             _ model: NSManagedObjectModel) throws -> NSPersistentStoreCoordinator {
55     do {
56         return try createCoordinator(config, model)
57     } catch {
58         let nserror = error as NSError
59         // Data Modelが更新されていたらストアファイルを削除してもう一度
60         if nserror.domain == NSCocoaErrorDomain,
61             (nserror.code == 134130 || nserror.code == 134110),
62             config.tryRemake {
63             remove(name: config.fileName)
64             do {
65                 return try createCoordinator(config, model)
66             } catch {
67                 print("Fail crrate NSPersistentStoreCoordinator twice.")
68             }
69         }
70         throw error
71     }
72 }
73 private func createCoordinator(_ config: CoreDataConfiguration,
74                                _ model: NSManagedObjectModel) throws -> NSPersistentStoreCoordinator {
75     if !checkDirectory(ApplicationDirecrories.support) {
76         let failureReason = "Can not use directory \(ApplicationDirecrories.support.path)"
77         throw CoreDataError.couldNotCreateCoordinator(failureReason)
78     }
79     
80     let coordinator: NSPersistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: model)
81     let url = ApplicationDirecrories.support.appendingPathComponent(config.fileName)
82     do {
83         try coordinator.addPersistentStore(ofType: config.type,
84                                            configurationName: nil,
85                                            at: url,
86                                            options: config.options)
87     } catch {
88         throw error
89     }
90     return coordinator
91 }
92 private func createContext(_ coordinator: NSPersistentStoreCoordinator) -> NSManagedObjectContext {
93     let moc = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
94     moc.persistentStoreCoordinator = coordinator
95     moc.undoManager = nil
96     return moc
97 }