diff --git a/AppleLibs/Utils/CoreData/ContextHolder.swift b/AppleLibs/Utils/CoreData/ContextHolder.swift new file mode 100644 index 0000000000000000000000000000000000000000..9271e601d204422e71bb3fa60060b1bed38a99e5 --- /dev/null +++ b/AppleLibs/Utils/CoreData/ContextHolder.swift @@ -0,0 +1,19 @@ +// +// ContextHolder.swift +// WolfManagementMobile +// +// Created by Tobias on 08.07.20. +// Copyright © 2020 Tobias. All rights reserved. +// + +import Foundation +import CoreData + +protocol ContextHolder +{ + var dataContainer: NSPersistentContainer { get } + + // MARK: - Core Data Saving support + + func saveContext() +} diff --git a/AppleLibs/Utils/CoreData/CoreData+Extended.swift b/AppleLibs/Utils/CoreData/CoreData+Extended.swift new file mode 100644 index 0000000000000000000000000000000000000000..50bcd876dd9489c336dc7b4249e51c5eaa118931 --- /dev/null +++ b/AppleLibs/Utils/CoreData/CoreData+Extended.swift @@ -0,0 +1,130 @@ +// +// CoreDataExtension.swift +// DocumentRepositoryMobile +// +// Created by Tobias on 19.01.19. +// Copyright © 2019 Tobias. All rights reserved. +// + +import UIKit +import CoreData +import Resolver +import Logging + +class AppContextHolder: ContextHolder +{ + private static let logger = Logger(label: "de.tobias.AppleLibs.coredata") + + // MARK: - Core Data stack + lazy var dataContainer: NSPersistentContainer = { + let container = NSPersistentContainer(name: "DataModel") + container.loadPersistentStores(completionHandler: { (_, error) in + if let error = error as NSError? { + fatalError("Unresolved error \(error), \(error.userInfo)") + } + }) + return container + }() + + // MARK: - Core Data Saving support + + func saveContext() { + saveContext(context: dataContainer.viewContext) + } + + private func saveContext(context: NSManagedObjectContext) { + if context.hasChanges { + do { + try context.save() + } catch { + // Replace this implementation with code to handle the error appropriately. + // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. + let error = error as NSError + AppContextHolder.logger.error("Unresolved error \(error), \(error.userInfo)") + } + } + } +} + +extension NSManagedObject +{ + private static let logger = Logger(label: "de.tobias.AppleLibs.coredata") + + static var contextHolder: ContextHolder { + Resolver.resolve() + } + + static var className: String { + NSStringFromClass(self).components(separatedBy: ".").last! + } + + static var context: NSManagedObjectContext { + return contextHolder.dataContainer.viewContext + } + + class func create() -> NSManagedObject? { + // logger.info("Create CoreData Object \(className)") + let context = NSManagedObject.context + + let entity = NSEntityDescription.entity(forEntityName: className, in: context) + return NSManagedObject(entity: entity!, insertInto: context) + } + + class func list<T: NSManagedObject>() -> [T] { + let request = NSFetchRequest<NSFetchRequestResult>(entityName: className) + request.returnsObjectsAsFaults = false + do { + var data: [T] = [] + + let result = try NSManagedObject.context.fetch(request).compactMap { + $0 as? T + } + for item in result { + data.append(item) + } + return data + } catch { + logger.error("Failed to list CoreData objects \(error)") + } + return [] + } + + func save() { + if let context = managedObjectContext { + do { + try context.save() + } catch let error as NSError { + NSManagedObject.logger.error("Failed to save core data context: \(error)") + } + } + } + + class func save() { + contextHolder.saveContext() + } + + class func delete(object: NSManagedObject?) { + if let object: NSManagedObject = object { + context.delete(object) + } + } + + class func deleteWhere(predicate: (NSManagedObject) -> Bool) { + list().filter(predicate).forEach { + context.delete($0) + } + } + + class func deleteAll() { + let context = NSManagedObject.context + + let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: className) + let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest) + + do { + try context.execute(deleteRequest) + } catch let error as NSError { + logger.error("Failed to delete core data objects \(error)") + } + } +}