1
1
mirror of https://github.com/qvacua/vimr.git synced 2024-11-27 06:04:07 +03:00
vimr/VimR/VimR/CoreDataStack.swift
2022-06-26 15:19:30 +02:00

115 lines
3.2 KiB
Swift

/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
import Commons
import CoreData
import Foundation
import os
final class CoreDataStack {
enum Error: Swift.Error {
case noCacheFolder
case pathDoesNotExit
case pathNotFolder
case unableToComplete(Swift.Error)
}
enum StoreLocation {
case temp(String)
case cache(String)
case path(String)
}
let container: NSPersistentContainer
let storeFile: URL
var storeLocation: URL { self.storeFile.parent }
var deleteOnDeinit: Bool
func newBackgroundContext() -> NSManagedObjectContext {
let context = self.container.newBackgroundContext()
context.undoManager = nil
return context
}
init(modelName: String, storeLocation: StoreLocation, deleteOnDeinit: Bool = false) throws {
self.deleteOnDeinit = deleteOnDeinit
self.container = NSPersistentContainer(name: modelName)
let fileManager = FileManager.default
let url: URL
switch storeLocation {
case let .temp(folderName):
let parentUrl = fileManager
.temporaryDirectory
.appendingPathComponent(folderName)
try fileManager.createDirectory(at: parentUrl, withIntermediateDirectories: true)
url = parentUrl.appendingPathComponent(modelName)
case let .cache(folderName):
guard let cacheUrl = fileManager.urls(for: .cachesDirectory, in: .userDomainMask).first else {
throw Error.noCacheFolder
}
let parentUrl = cacheUrl.appendingPathComponent(folderName)
try fileManager.createDirectory(at: parentUrl, withIntermediateDirectories: true)
url = parentUrl.appendingPathComponent(modelName)
case let .path(path):
guard fileManager.fileExists(atPath: path) else { throw Error.pathDoesNotExit }
let parentFolder = URL(fileURLWithPath: path)
guard parentFolder.hasDirectoryPath else { throw Error.pathNotFolder }
url = parentFolder.appendingPathComponent(modelName)
}
self.container.persistentStoreDescriptions = [NSPersistentStoreDescription(url: url)]
self.storeFile = url
self.log.info("Created Core Data store in \(self.storeLocation)")
let condition = ConditionVariable()
var error: Swift.Error?
self.container.loadPersistentStores { _, err in
error = err
condition.broadcast()
}
condition.wait(for: 5)
if let err = error { throw Error.unableToComplete(err) }
self.container.viewContext.undoManager = nil
}
func deleteStore() throws {
guard self.deleteOnDeinit else { return }
guard let store = self.container.persistentStoreCoordinator.persistentStore(
for: self.storeFile
) else { return }
try self.container.persistentStoreCoordinator.remove(store)
let parentFolder = self.storeLocation
let fileManager = FileManager.default
guard fileManager.fileExists(atPath: parentFolder.path) else { return }
try fileManager.removeItem(at: parentFolder)
self.log.info("Deleted store at \(self.storeLocation)")
}
deinit {
guard self.deleteOnDeinit else { return }
do {
try self.deleteStore()
} catch {
self.log.error("Could not delete store at \(self.storeLocation): \(error)")
}
}
private let log = OSLog(subsystem: Defs.loggerSubsystem, category: Defs.LoggerCategory.service)
}