Page MenuHomeMusing Studio

LocalStorageManager.swift
No OneTemporary

LocalStorageManager.swift

import CoreData
#if os(iOS)
import UIKit
#elseif os(macOS)
import AppKit
#endif
final class LocalStorageManager {
private let logger = Logging(for: String(describing: LocalStorageManager.self))
public static var standard = LocalStorageManager()
public let container: NSPersistentContainer
private let containerName = "LocalStorageModel"
private init() {
container = NSPersistentContainer(name: containerName)
setupStore(in: container)
registerObservers()
}
func saveContext() {
if container.viewContext.hasChanges {
do {
logger.log("Saving context to local store started...")
try container.viewContext.save()
logger.log("Context saved to local store.")
} catch {
logger.logCrashAndSetFlag(error: LocalStoreError.couldNotSaveContext)
}
}
}
func purgeUserCollections() throws {
let fetchRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "WFACollection")
let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
do {
logger.log("Purging user collections from local store...")
try container.viewContext.executeAndMergeChanges(using: deleteRequest)
logger.log("User collections purged from local store.")
} catch {
logger.log("\(LocalStoreError.couldNotPurgeCollections.localizedDescription)", level: .error)
throw LocalStoreError.couldNotPurgeCollections
}
}
}
private extension LocalStorageManager {
var oldStoreURL: URL {
let appSupport = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask).first!
return appSupport.appendingPathComponent("LocalStorageModel.sqlite")
}
var sharedStoreURL: URL {
let id = "group.com.abunchtell.writefreely"
let groupContainer = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: id)!
return groupContainer.appendingPathComponent("LocalStorageModel.sqlite")
}
func setupStore(in container: NSPersistentContainer) {
if !FileManager.default.fileExists(atPath: oldStoreURL.path) {
container.persistentStoreDescriptions.first!.url = sharedStoreURL
}
container.loadPersistentStores { _, error in
self.logger.log("Loading local store...")
if let error = error {
self.logger.logCrashAndSetFlag(error: LocalStoreError.couldNotLoadStore(error.localizedDescription))
}
self.logger.log("Loaded local store.")
}
migrateStore(for: container)
container.viewContext.automaticallyMergesChangesFromParent = true
container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
}
func migrateStore(for container: NSPersistentContainer) {
// Check if the shared store exists before attempting a migration — for example, in case we've already attempted
// and successfully completed a migration, but the deletion of the old store failed for some reason.
guard !FileManager.default.fileExists(atPath: sharedStoreURL.path) else { return }
let coordinator = container.persistentStoreCoordinator
// Get a reference to the old store.
guard let oldStore = coordinator.persistentStore(for: oldStoreURL) else {
return
}
// Attempt to migrate the old store over to the shared store URL.
do {
self.logger.log("Migrating local store to shared store...")
try coordinator.migratePersistentStore(oldStore,
to: sharedStoreURL,
options: nil,
withType: NSSQLiteStoreType)
self.logger.log("Migrated local store to shared store.")
} catch {
logger.logCrashAndSetFlag(error: LocalStoreError.couldNotMigrateStore(error.localizedDescription))
}
// Attempt to delete the old store.
do {
logger.log("Deleting migrated local store...")
try FileManager.default.removeItem(at: oldStoreURL)
logger.log("Deleted migrated local store.")
} catch {
logger.logCrashAndSetFlag(
error: LocalStoreError.couldNotDeleteStoreAfterMigration(error.localizedDescription)
)
}
}
func registerObservers() {
let center = NotificationCenter.default
#if os(iOS)
let notification = UIApplication.willResignActiveNotification
#elseif os(macOS)
let notification = NSApplication.willResignActiveNotification
#endif
// We don't need to worry about removing this observer because we're targeting iOS 9+ / macOS 10.11+; the
// system will clean this up the next time it would be posted to.
// See: https://developer.apple.com/documentation/foundation/notificationcenter/1413994-removeobserver
// And: https://developer.apple.com/documentation/foundation/notificationcenter/1407263-removeobserver
// swiftlint:disable:next discarded_notification_center_observer
center.addObserver(forName: notification, object: nil, queue: nil, using: self.saveContextOnResignActive)
}
func saveContextOnResignActive(_ notification: Notification) {
saveContext()
}
}

File Metadata

Mime Type
text/plain
Expires
Sat, Nov 15, 9:17 AM (1 d, 13 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3491210

Event Timeline