forked from jessesquires/JSQCoreDataKit
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCoreDataStackFactory.swift
More file actions
147 lines (116 loc) · 5.39 KB
/
CoreDataStackFactory.swift
File metadata and controls
147 lines (116 loc) · 5.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
//
// Created by Jesse Squires
// https://www.jessesquires.com
//
//
// Documentation
// https://jessesquires.github.io/JSQCoreDataKit
//
//
// GitHub
// https://github.com/jessesquires/JSQCoreDataKit
//
//
// License
// Copyright © 2015 Jesse Squires
// Released under an MIT license: https://opensource.org/licenses/MIT
//
import CoreData
import Foundation
/**
An instance of `CoreDataStackFactory` is responsible for creating instances of `CoreDataStack`.
Because the adding of the persistent store to the persistent store coordinator during initialization
of a `CoreDataStack` can take an unknown amount of time, you should not perform this operation on the main queue.
See this [guide](https://developer.apple.com/library/prerelease/ios/documentation/Cocoa/Conceptual/CoreData/IntegratingCoreData.html#//apple_ref/doc/uid/TP40001075-CH9-SW1) for more details.
- warning: You should not create instances of `CoreDataStack` directly. Use a `CoreDataStackFactory` instead.
*/
public struct CoreDataStackFactory: Equatable {
// MARK: Properties
/// The model for the stack that the factory produces.
public let model: CoreDataModel
/**
A dictionary that specifies options for the store that the factory produces.
The default value is `DefaultStoreOptions`.
*/
public let options: PersistentStoreOptions?
// MARK: Initialization
/**
Constructs a new `CoreDataStackFactory` instance with the specified `model` and `options`.
- parameter model: The model describing the stack.
- parameter options: Options for the persistent store.
- returns: A new `CoreDataStackFactory` instance.
*/
public init(model: CoreDataModel, options: PersistentStoreOptions? = defaultStoreOptions) {
self.model = model
self.options = options
}
// MARK: Creating a stack
/**
Initializes a new `CoreDataStack` instance using the factory's `model` and `options`.
- warning: If a queue is provided, this operation is performed asynchronously on the specified queue,
and the completion closure is executed asynchronously on the main queue.
If `queue` is `nil`, then this method and the completion closure execute synchronously on the current queue.
- parameter queue: The queue on which to initialize the stack.
The default is a background queue with a "user initiated" quality of service class.
If passing `nil`, this method is executed synchronously on the queue from which the method was called.
- parameter completion: The closure to be called once initialization is complete.
If a queue is provided, this is called asynchronously on the main queue.
Otherwise, this is executed on the thread from which the method was originally called.
*/
public func createStack(onQueue queue: DispatchQueue? = .global(qos: .userInitiated),
completion: @escaping (StackResult) -> Void) {
let isAsync = (queue != nil)
let creationClosure = {
let storeCoordinator: NSPersistentStoreCoordinator
do {
storeCoordinator = try self.createStoreCoordinator()
} catch {
if isAsync {
DispatchQueue.main.async {
completion(.failure(error as NSError))
}
} else {
completion(.failure(error as NSError))
}
return
}
let backgroundContext = self.createContext(.privateQueueConcurrencyType, name: "background")
backgroundContext.persistentStoreCoordinator = storeCoordinator
let mainContext = self.createContext(.mainQueueConcurrencyType, name: "main")
mainContext.persistentStoreCoordinator = storeCoordinator
let stack = CoreDataStack(model: self.model,
mainContext: mainContext,
backgroundContext: backgroundContext,
storeCoordinator: storeCoordinator)
if isAsync {
DispatchQueue.main.async {
completion(.success(stack))
}
} else {
completion(.success(stack))
}
}
if let queue = queue {
queue.async(execute: creationClosure)
} else {
creationClosure()
}
}
// MARK: Private
private func createStoreCoordinator() throws -> NSPersistentStoreCoordinator {
let storeCoordinator = NSPersistentStoreCoordinator(managedObjectModel: model.managedObjectModel)
try storeCoordinator.addPersistentStore(ofType: model.storeType.type,
configurationName: nil,
at: model.storeURL,
options: options)
return storeCoordinator
}
private func createContext(_ concurrencyType: NSManagedObjectContextConcurrencyType,
name: String) -> NSManagedObjectContext {
let context = NSManagedObjectContext(concurrencyType: concurrencyType)
context.mergePolicy = NSMergePolicy(merge: .mergeByPropertyStoreTrumpMergePolicyType)
let contextName = "JSQCoreDataKit.CoreDataStack.context."
context.name = contextName + name
return context
}
}