From 49a21909edf8fef50907e5d340da584268431f6f Mon Sep 17 00:00:00 2001 From: dankito Date: Sat, 10 Oct 2020 16:07:56 +0200 Subject: [PATCH] Moved creating CoreData PersistentContainer to CoreDataBankingPersistence --- .../BankingiOSApp/AppDelegate.swift | 46 ---------------- .../BankingiOSApp/SceneDelegate.swift | 17 +++--- .../CoreDataBankingPersistence.swift | 52 +++++++++++++++++-- 3 files changed, 54 insertions(+), 61 deletions(-) diff --git a/ui/BankingiOSApp/BankingiOSApp/AppDelegate.swift b/ui/BankingiOSApp/BankingiOSApp/AppDelegate.swift index 07d9dbef..5f993b77 100644 --- a/ui/BankingiOSApp/BankingiOSApp/AppDelegate.swift +++ b/ui/BankingiOSApp/BankingiOSApp/AppDelegate.swift @@ -1,5 +1,4 @@ import UIKit -import CoreData import BankingUiSwift @@ -25,50 +24,5 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } - // MARK: - Core Data stack - - lazy var persistentContainer: NSPersistentContainer = { - /* - The persistent container for the application. This implementation - creates and returns a container, having loaded the store for the - application to it. This property is optional since there are legitimate - error conditions that could cause the creation of the store to fail. - */ - let container = NSPersistentContainer(name: "BankingiOSApp") - container.loadPersistentStores(completionHandler: { (storeDescription, error) in - if let error = error as NSError? { - // 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. - - /* - Typical reasons for an error here include: - * The parent directory does not exist, cannot be created, or disallows writing. - * The persistent store is not accessible, due to permissions or data protection when the device is locked. - * The device is out of space. - * The store could not be migrated to the current model version. - Check the error message to determine what the actual problem was. - */ - fatalError("Unresolved error \(error), \(error.userInfo)") - } - }) - return container - }() - - // MARK: - Core Data Saving support - - func saveContext () { - let context = persistentContainer.viewContext - 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 nserror = error as NSError - fatalError("Unresolved error \(nserror), \(nserror.userInfo)") - } - } - } - } diff --git a/ui/BankingiOSApp/BankingiOSApp/SceneDelegate.swift b/ui/BankingiOSApp/BankingiOSApp/SceneDelegate.swift index 5e418d38..4658befe 100644 --- a/ui/BankingiOSApp/BankingiOSApp/SceneDelegate.swift +++ b/ui/BankingiOSApp/BankingiOSApp/SceneDelegate.swift @@ -7,18 +7,15 @@ import BankingUiSwift class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? + + var persistence: CoreDataBankingPersistence? func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. - // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). - - // Get the managed object context from the shared persistent container. - let appDelegate = UIApplication.shared.delegate as! AppDelegate - let context = appDelegate.persistentContainer.viewContext - setupBankingUi(context: context) + setupBankingUi() let authenticationService = AuthenticationService() @@ -39,17 +36,17 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { } } - private func setupBankingUi(context: NSManagedObjectContext) { + private func setupBankingUi() { let appDataFolder = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first ?? Bundle.main.resourceURL?.absoluteString ?? "" - let persistence = CoreDataBankingPersistence(context: context) + let persistence = CoreDataBankingPersistence() + self.persistence = persistence let dataFolder = URL(fileURLWithPath: "data", isDirectory: true, relativeTo: URL(fileURLWithPath: appDataFolder)) let presenter = BankingPresenterSwift(dataFolder: dataFolder, router: SwiftUiRouter(), webClient: UrlSessionWebClient(), persistence: persistence, transactionPartySearcher: persistence, bankIconFinder: SwiftBankIconFinder(), serializer: NoOpSerializer(), asyncRunner: DispatchQueueAsyncRunner()) - DependencyInjector.register(dependency: persistence) DependencyInjector.register(dependency: presenter) } @@ -93,7 +90,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { // to restore the scene back to its current state. // Save changes in the application's managed object context when the application transitions to the background. - (UIApplication.shared.delegate as? AppDelegate)?.saveContext() + persistence?.saveContext() } diff --git a/ui/BankingiOSApp/BankingiOSApp/persistence/CoreDataBankingPersistence.swift b/ui/BankingiOSApp/BankingiOSApp/persistence/CoreDataBankingPersistence.swift index 23b823e9..913035a1 100644 --- a/ui/BankingiOSApp/BankingiOSApp/persistence/CoreDataBankingPersistence.swift +++ b/ui/BankingiOSApp/BankingiOSApp/persistence/CoreDataBankingPersistence.swift @@ -2,20 +2,62 @@ import Foundation import CoreData import UIKit import BankingUiSwift +import EncryptedCoreData class CoreDataBankingPersistence: IBankingPersistence, ITransactionPartySearcher { private let mapper = Mapper() - private let context: NSManagedObjectContext - - init(context: NSManagedObjectContext) { - self.context = context + lazy var persistentContainer: NSPersistentContainer = { + /* + The persistent container for the application. This implementation + creates and returns a container, having loaded the store for the + application to it. This property is optional since there are legitimate + error conditions that could cause the creation of the store to fail. + */ + let container = NSPersistentContainer(name: "BankingiOSApp") + container.loadPersistentStores(completionHandler: { (storeDescription, error) in + if let error = error as NSError? { + // 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. + + /* + Typical reasons for an error here include: + * The parent directory does not exist, cannot be created, or disallows writing. + * The persistent store is not accessible, due to permissions or data protection when the device is locked. + * The device is out of space. + * The store could not be migrated to the current model version. + Check the error message to determine what the actual problem was. + */ + fatalError("Unresolved error \(error), \(error.userInfo)") + } + }) + // TODO: still needed? // to fix merging / updating cached objects, see Mapper - context.mergePolicy = NSMergePolicy(merge: NSMergePolicyType.mergeByPropertyObjectTrumpMergePolicyType) + container.viewContext.mergePolicy = NSMergePolicy(merge: NSMergePolicyType.mergeByPropertyObjectTrumpMergePolicyType) + + return container + }() + + lazy var context: NSManagedObjectContext = { + return persistentContainer.viewContext + }() + + func saveContext () { + let context = persistentContainer.viewContext + 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 nserror = error as NSError + fatalError("Unresolved error \(nserror), \(nserror.userInfo)") + } + } }