// // PersistenceService.swift // Persistence // // Created by Javier Cicchelli on 10/04/2023. // Copyright © 2023 Röck+Cöde. All rights reserved. // import CoreData public struct PersistenceService { // MARK: Properties public static let shared = PersistenceService() public static let inMemory = PersistenceService(inMemory: true) public let container: NSPersistentContainer // MARK: Initialisers init(inMemory: Bool = false) { guard let modelURL = Bundle.module.url(forResource: .Model.name, withExtension: .Model.extension), let managedObjectModel = NSManagedObjectModel(contentsOf: modelURL) else { fatalError("Could not load the model from the library.") } container = NSPersistentContainer( name: .Model.name, managedObjectModel: managedObjectModel ) setContainer(inMemory) } } // MARK: - Service extension PersistenceService: Service { // MARK: Properties public var viewContext: NSManagedObjectContext { container.viewContext } // MARK: Functions public func makeTaskContext() -> NSManagedObjectContext { let taskContext = container.newBackgroundContext() taskContext.automaticallyMergesChangesFromParent = true taskContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy return taskContext } public func makeChildContext() -> NSManagedObjectContext { let context = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType) context.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy context.parent = container.viewContext context.automaticallyMergesChangesFromParent = true return context } public func save(context: NSManagedObjectContext) { guard context.hasChanges else { return } do { try context.save() } catch { let nserror = error as NSError fatalError("Unresolved error \(nserror), \(nserror.userInfo)") } } public func save(childContext context: NSManagedObjectContext) { guard context.hasChanges else { return } do { try context.save() guard let parent = context.parent, parent == container.viewContext else { return } try parent.performAndWait { try parent.save() } } catch { let nserror = error as NSError fatalError("Unresolved error \(nserror), \(nserror.userInfo)") } } } // MARK: - Helpers private extension PersistenceService { func setContainer(_ inMemory: Bool) { container.persistentStoreDescriptions = [ NSPersistentStoreDescription(url: inMemory ? URL(fileURLWithPath: "/dev/null") : NSPersistentContainer.defaultDirectoryURL().appending(path: "\(String.Model.name).sqlite") ) ] container.loadPersistentStores { _, error in if let error = error as NSError? { fatalError("Unresolved error \(error), \(error.userInfo)") } } container.viewContext.automaticallyMergesChangesFromParent = true } } // MARK: - String+Constants private extension String { enum Model { static let name = "Model" static let `extension` = "momd" } }