OSDN Git Service

バージョンを1.9b19に更新
[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     
13     case applicationDirectoryIsFile
14     case couldNotCreateModel
15     case couldNotCreateCoordinator(String)
16 }
17
18 func remove(name: String) {
19     
20     ["", "-wal", "-shm"]
21         .map { name + $0 }
22         .map { ApplicationDirecrories.support.appendingPathComponent($0) }
23         .forEach { removeDataFile(at: $0) }
24 }
25
26 func genarate(_ config: CoreDataConfiguration) throws -> (model: NSManagedObjectModel, coordinator: NSPersistentStoreCoordinator, moc: NSManagedObjectContext) {
27     
28     do {
29         
30         let model = try createModel(config)
31         let coordinator = try getCoordinator(config, model)
32         let moc = createContext(coordinator)
33         
34         return (model: model, coordinator: coordinator, moc: moc)
35         
36     } catch {
37         
38         throw error
39     }
40 }
41
42 private func removeDataFile(at url: URL) {
43     
44     do {
45         
46         try FileManager.default.removeItem(at: url)
47         
48     } catch {
49         
50         print("Could not remove file for URL (\(url))")
51     }
52 }
53
54 // MARK: - NSManagedObjectContext and ...
55 private  func createModel(_ config: CoreDataConfiguration) throws -> NSManagedObjectModel {
56     
57     guard let modelURL = Bundle.main.url(forResource: config.modelName, withExtension: "momd"),
58         let model = NSManagedObjectModel(contentsOf: modelURL)
59         else {
60             throw CoreDataError.couldNotCreateModel
61     }
62     
63     return model
64 }
65 private func getCoordinator(_ config: CoreDataConfiguration, _ model: NSManagedObjectModel) throws -> NSPersistentStoreCoordinator {
66     
67     do {
68         
69         return try createCoordinator(config, model)
70         
71     } catch {
72         
73         let nserror = error as NSError
74         // Data Modelが更新されていたらストアファイルを削除してもう一度
75         if nserror.domain == NSCocoaErrorDomain,
76             (nserror.code == 134130 || nserror.code == 134110),
77             config.tryRemake {
78             
79             remove(name: config.fileName)
80             
81             do {
82                 
83                 return try createCoordinator(config, model)
84                 
85             } catch {
86                 
87                 print("Fail crrate NSPersistentStoreCoordinator twice.")
88             }
89         }
90         
91         throw error
92     }
93 }
94
95 private func createCoordinator(_ config: CoreDataConfiguration, _ model: NSManagedObjectModel) throws -> NSPersistentStoreCoordinator {
96     
97     if !checkDirectory(ApplicationDirecrories.support) {
98         
99         let failureReason = "Can not use directory \(ApplicationDirecrories.support.path)"
100         
101         throw CoreDataError.couldNotCreateCoordinator(failureReason)
102     }
103     
104     let coordinator: NSPersistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: model)
105     let url = ApplicationDirecrories.support.appendingPathComponent(config.fileName)
106     
107     do {
108         
109         try coordinator.addPersistentStore(ofType: config.type,
110                                            configurationName: nil,
111                                            at: url,
112                                            options: config.options)
113         
114     } catch {
115         
116         throw error
117     }
118     
119     return coordinator
120 }
121
122 private func createContext(_ coordinator: NSPersistentStoreCoordinator) -> NSManagedObjectContext {
123     
124     let moc = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
125     moc.persistentStoreCoordinator = coordinator
126     moc.undoManager = nil
127     
128     return moc
129 }