-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBaseCoreDataStack.swift
More file actions
130 lines (102 loc) · 3.93 KB
/
BaseCoreDataStack.swift
File metadata and controls
130 lines (102 loc) · 3.93 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
//
// BaseCoreDataStack.swift
//
// Copyright 2023 OpenAlloc LLC
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
//
import CoreData
import os
import Collections
// TODO:
// var isICloudContainerAvailable: Bool {
// FileManager.default.ubiquityIdentityToken != nil
// }
extension BaseCoreDataStack: ObservableObject {}
// Multi-store support
// CloudKit support
// History change support (for de-duplication)
// support for segregated test/preview containers, using fileNamePrefix
open class BaseCoreDataStack {
// MARK: - Parameters
let modelName: String
let baseFileName: String
let cloudPrefix: String?
let fileNamePrefix: String
let appTransactionAuthorName: String
let storeKeys: [String]
public init(modelName: String,
baseFileName: String,
cloudPrefix: String? = nil,
fileNamePrefix: String = "",
appTransactionAuthorName: String = "app",
storeKeys: [String] = [BaseCoreDataStack.defaultStoreKey])
{
self.modelName = modelName
self.baseFileName = baseFileName
self.cloudPrefix = cloudPrefix
self.fileNamePrefix = fileNamePrefix
self.appTransactionAuthorName = appTransactionAuthorName
self.storeKeys = storeKeys
}
deinit {
deinitStoreRemoteChangeNotification()
}
// MARK: - Properties
public private(set) lazy var container: NSPersistentContainer = {
precondition(Thread.isMainThread)
let container = getContainer()
// receive remote notifications of changes
initStoreRemoteChangeNotification(container)
return container
}()
// MARK: - Stores Support
public static let defaultStoreKey = ""
public typealias StoresDict = OrderedDictionary<String, NSPersistentStoreDescription>
public lazy var stores: StoresDict = storeKeys.reduce(into: [:]) { dict, key in
dict[key] = getStoreDescription(storeKey: key)
}
// MARK: - Model Support
open func loadModel(modelName _: String) -> NSManagedObjectModel {
fatalError("You must override loadModel()")
}
// MARK: - History / Remote Notification support
lazy var tokenFileURL: URL = getTokenFileURL(name: baseFileName)
// an operation queue for handling history processing tasks, including
// * watching changes
// * deduplicating
// * triggering UI updates, if needed
lazy var historyQueue: OperationQueue = {
let q = OperationQueue()
q.maxConcurrentOperationCount = 1
return q
}()
// override this for de-duping
// NOTE: that this is happening on background thread
// NOTE: handler is responsible for saving context
open func handleInsert(backgroundContext _: NSManagedObjectContext,
entityName _: String,
objectID _: NSManagedObjectID,
storeID _: String)
{
fatalError("You must override handleInsert()")
}
// MARK: - Helpers
public let logger = Logger(subsystem: Bundle.main.bundleIdentifier!,
category: String(describing: BaseCoreDataStack.self))
// MARK: - Not used yet
// public private(set) lazy var backgroundContext: NSManagedObjectContext = {
// precondition(Thread.isMainThread)
// let bc = container.newBackgroundContext()
// bc.transactionAuthor = appTransactionAuthorName
// bc.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
// return bc
// }()
// lazy var model: NSManagedObjectModel = {
// let bundle = Bundle.module
// let modelURL = bundle.url(forResource: modelName, withExtension: ".momd")!
// return NSManagedObjectModel(contentsOf: modelURL)!
// }()
}