Skip to content

Instantly share code, notes, and snippets.

@suhitp
Last active December 21, 2021 10:34
Show Gist options
  • Save suhitp/6a2d0fbb176d19f8fcbdd5e8167e9b45 to your computer and use it in GitHub Desktop.
Save suhitp/6a2d0fbb176d19f8fcbdd5e8167e9b45 to your computer and use it in GitHub Desktop.
// MARK: CoreDataStack
final class CoreDataStack: CoreDataStackProvider {
// MARK: Properties
private let persistentContainer: NSPersistentContainer
/// MainContext
private(set) lazy var mainContext: NSManagedObjectContext = {
let viewContext = persistentContainer.viewContext
viewContext.automaticallyMergesChangesFromParent = false
viewContext.mergePolicy = NSMergePolicy.mergeByPropertyObjectTrump
viewContext.undoManager = nil
viewContext.shouldDeleteInaccessibleFaults = true
return persistentContainer.viewContext
}()
/// NewBackgroundContext
var newBackgroundContext: NSManagedObjectContext {
let context = persistentContainer.newBackgroundContext()
context.mergePolicy = NSMergePolicy.mergeByPropertyObjectTrump
context.undoManager = nil
return context
}
/// BackgroundContext
private(set) lazy var backgroundContext: NSManagedObjectContext = {
let context = persistentContainer.newBackgroundContext()
context.mergePolicy = NSMergePolicy.mergeByPropertyObjectTrump
context.undoManager = nil
return context
}()
// MARK: init
init(persistentContainer: NSPersistentContainer) {
self.persistentContainer = persistentContainer
}
}
// MARK: PersistentContainer
final class StorePersistentContainer: NSPersistentContainer {
// MARK: Properties
private var isLoaded: Bool = false
private var inMemoryStore: Bool = false
/// Constants
enum Constants {
static let managedObjectModelNotFoundError = "LocalizationStore model not found or corrupted"
static let localizationStore = "CDStore"
static let momd = "momd"
static let sqliteFileName = "CDStore.sqlite"
static let folderName = "CDDatabase"
}
/// NSManagedObjectModel
private(set) static var managedObjectModel: NSManagedObjectModel = {
let bundle = Bundle(for: LocalizationPersistentContainer.self)
guard let url = bundle.url(forResource: Constants.localizationStore, withExtension: Constants.momd),
let model = NSManagedObjectModel(contentsOf: url) else {
ErrorUtility.assertionFailureWithLog(localizationCodeLogModule, Constants.managedObjectModelNotFoundError)
preconditionFailure(Constants.managedObjectModelNotFoundError)
}
return model
}()
private var storeURL: URL {
if inMemoryStore {
let url = URL(fileURLWithPath: "/dev/null")
return url
} else {
let defaultDirectoryURL = NSPersistentContainer.defaultDirectoryURL()
let url = defaultDirectoryURL.appendingPathComponent(Constants.sqliteFileName)
return url
}
}
// MARK: Init
convenience init(name: String, inMemoryStore: Bool = false) {
self.init(name: name, managedObjectModel: Self.managedObjectModel)
self.inMemoryStore = inMemoryStore
setupPerstistentStoreDescription()
loadPeristentStore()
}
// MARK: NSPersistentStoreDescription
func setupPerstistentStoreDescription() {
let description = NSPersistentStoreDescription(url: storeURL)
if inMemoryStore {
description.type = NSInMemoryStoreType
description.shouldAddStoreAsynchronously = false
} else {
description.type = NSSQLiteStoreType
description.shouldAddStoreAsynchronously = true
}
description.shouldMigrateStoreAutomatically = true
description.shouldInferMappingModelAutomatically = true
description.isReadOnly = false
persistentStoreDescriptions = [description]
}
// MARK: loadPersistentStores
func loadPeristentStore() {
if isLoaded {
return
}
loadPersistentStores { [weak self] (_, error) in
if let error = error as NSError? {
print("Unresolved Error in loadPersistentStores \(error), \(error.userInfo)")
}
self?.isLoaded = true
}
}
// MARK: Overriden Methods
override class func defaultDirectoryURL() -> URL {
do {
let databaseDirectoryURL: URL = try FileManager.createDBDirectory(
withName: Constants.folderName,
subFolderPath: Constants.localizationStore
)
#if DEBUG
print("Localization DB Path: \(databaseDirectoryURL.path)")
#endif
return databaseDirectoryURL
} catch {
print("Could not get LocalizationStore defaultDirectoryURL path: \(error.localizedDescription)")
return NSPersistentContainer.defaultDirectoryURL()
}
}
func resetStore() throws {
do {
if #available(iOS 15.0, *) {
let storeType: NSPersistentStore.StoreType = inMemoryStore ? .inMemory : .sqlite
try self.persistentStoreCoordinator.destroyPersistentStore(at: storeURL, type: storeType)
try self.persistentStoreCoordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: storeURL, options: nil)
} else {
let storeType: String = inMemoryStore ? NSInMemoryStoreType : NSSQLiteStoreType
try self.persistentStoreCoordinator.destroyPersistentStore(at: storeURL, ofType: storeType)
try self.persistentStoreCoordinator.addPersistentStore(ofType: storeType, configurationName: nil, at: storeURL, options: nil)
}
}
catch {
print(error.localizedDescription)
throw error
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment