fix issue with header not showing correct vote date split logic for Persistence into different files create class that deals with voting time, existing votes, and what should be shown based on that
105 lines
3.9 KiB
Swift
105 lines
3.9 KiB
Swift
//
|
|
// Persistence.swift
|
|
// Shared
|
|
//
|
|
// Created by Trey Tartt on 1/5/22.
|
|
//
|
|
|
|
import CoreData
|
|
import SwiftUI
|
|
|
|
class PersistenceController {
|
|
@AppStorage(UserDefaultsStore.Keys.useCloudKit.rawValue, store: GroupUserDefaults.groupDefaults) private var useCloudKit = false
|
|
|
|
static let shared = PersistenceController.persistenceController
|
|
|
|
private static var persistenceController: PersistenceController {
|
|
return PersistenceController(inMemory: false)
|
|
}
|
|
|
|
public var viewContext: NSManagedObjectContext {
|
|
return PersistenceController.shared.container.viewContext
|
|
}
|
|
|
|
public var switchContainerListeners = [(() -> Void)]()
|
|
|
|
public var earliestEntry: MoodEntry? {
|
|
let fetchRequest = NSFetchRequest<MoodEntry>(entityName: "MoodEntry")
|
|
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "forDate", ascending: true)]
|
|
let first = try! viewContext.fetch(fetchRequest).first
|
|
return first ?? nil
|
|
}
|
|
|
|
public var latestEntry: MoodEntry? {
|
|
let fetchRequest = NSFetchRequest<MoodEntry>(entityName: "MoodEntry")
|
|
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "forDate", ascending: true)]
|
|
let last = try! viewContext.fetch(fetchRequest).last
|
|
return last ?? nil
|
|
}
|
|
|
|
lazy var container: NSPersistentContainer = {
|
|
setupContainer()
|
|
}()
|
|
|
|
func switchContainer() {
|
|
try? viewContext.save()
|
|
container = setupContainer()
|
|
for item in switchContainerListeners {
|
|
item()
|
|
}
|
|
}
|
|
|
|
private func setupContainer() -> NSPersistentContainer {
|
|
if useCloudKit {
|
|
container = NSPersistentCloudKitContainer(name: "Feels")
|
|
} else {
|
|
container = NSCustomPersistentContainer(name: "Feels")
|
|
}
|
|
|
|
for description in container.persistentStoreDescriptions {
|
|
description.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
|
|
description.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
|
|
description.setOption(true as NSNumber, forKey: NSMigratePersistentStoresAutomaticallyOption)
|
|
description.setOption(true as NSNumber, forKey: NSInferMappingModelAutomaticallyOption)
|
|
}
|
|
|
|
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
|
|
self.container.viewContext.automaticallyMergesChangesFromParent = true
|
|
|
|
if let error = error as NSError? {
|
|
fatalError("Unresolved error \(error), \(error.userInfo)")
|
|
}
|
|
})
|
|
|
|
return container
|
|
}
|
|
|
|
init(inMemory: Bool = false) {
|
|
container = setupContainer()
|
|
}
|
|
}
|
|
|
|
extension NSManagedObjectContext {
|
|
/// Executes the given `NSBatchDeleteRequest` and directly merges the changes to bring the given managed object context up to date.
|
|
///
|
|
/// - Parameter batchDeleteRequest: The `NSBatchDeleteRequest` to execute.
|
|
/// - Throws: An error if anything went wrong executing the batch deletion.
|
|
public func executeAndMergeChanges(using batchDeleteRequest: NSBatchDeleteRequest) throws {
|
|
batchDeleteRequest.resultType = .resultTypeObjectIDs
|
|
let result = try execute(batchDeleteRequest) as? NSBatchDeleteResult
|
|
let changes: [AnyHashable: Any] = [NSDeletedObjectsKey: result?.result as? [NSManagedObjectID] ?? []]
|
|
NSManagedObjectContext.mergeChanges(fromRemoteContextSave: changes, into: [self])
|
|
}
|
|
}
|
|
|
|
class NSCustomPersistentContainer: NSPersistentContainer {
|
|
override open class func defaultDirectoryURL() -> URL {
|
|
var storeURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: Constants.groupShareId)
|
|
storeURL = storeURL?.appendingPathComponent("Feels.sqlite")
|
|
#if DEBUG
|
|
storeURL = storeURL?.appendingPathComponent("Feels-Debug.sqlite")
|
|
#endif
|
|
return storeURL!
|
|
}
|
|
}
|