فهرست منبع

Force initialization of Core DataStack before loadServices() method

polscm32 1 سال پیش
والد
کامیت
04b006427f
4فایلهای تغییر یافته به همراه65 افزوده شده و 30 حذف شده
  1. 33 20
      Model/CoreDataStack.swift
  2. 6 0
      Model/Helper/CoreDataError.swift
  3. 22 10
      Trio/Sources/Application/TrioApp.swift
  4. 4 0
      Trio/Sources/Logger/Logger.swift

+ 33 - 20
Model/CoreDataStack.swift

@@ -131,14 +131,14 @@ class CoreDataStack: ObservableObject {
         do {
         do {
             try await fetchPersistentHistoryTransactionsAndChanges()
             try await fetchPersistentHistoryTransactionsAndChanges()
         } catch {
         } catch {
-            debugPrint("\(error.localizedDescription)")
+            debug(.coreData, "\(error.localizedDescription)")
         }
         }
     }
     }
 
 
     private func fetchPersistentHistoryTransactionsAndChanges() async throws {
     private func fetchPersistentHistoryTransactionsAndChanges() async throws {
         let taskContext = newTaskContext()
         let taskContext = newTaskContext()
         taskContext.name = "persistentHistoryContext"
         taskContext.name = "persistentHistoryContext"
-//        debugPrint("Start fetching persistent history changes from the store ... \(DebuggingIdentifiers.inProgress)")
+//        debug(.coreData,"Start fetching persistent history changes from the store ... \(DebuggingIdentifiers.inProgress)")
 
 
         try await taskContext.perform {
         try await taskContext.perform {
             // Execute the persistent history change since the last transaction
             // Execute the persistent history change since the last transaction
@@ -153,7 +153,7 @@ class CoreDataStack: ObservableObject {
     }
     }
 
 
     private func mergePersistentHistoryChanges(from history: [NSPersistentHistoryTransaction]) {
     private func mergePersistentHistoryChanges(from history: [NSPersistentHistoryTransaction]) {
-//        debugPrint("Received \(history.count) persistent history transactions")
+//        debug(.coreData,"Received \(history.count) persistent history transactions")
         // Update view context with objectIDs from history change request
         // Update view context with objectIDs from history change request
         /// - Tag: mergeChanges
         /// - Tag: mergeChanges
         let viewContext = persistentContainer.viewContext
         let viewContext = persistentContainer.viewContext
@@ -175,14 +175,25 @@ class CoreDataStack: ObservableObject {
             let deleteHistoryTokensRequest = NSPersistentHistoryChangeRequest.deleteHistory(before: date)
             let deleteHistoryTokensRequest = NSPersistentHistoryChangeRequest.deleteHistory(before: date)
             do {
             do {
                 try taskContext.execute(deleteHistoryTokensRequest)
                 try taskContext.execute(deleteHistoryTokensRequest)
-                debugPrint("\(DebuggingIdentifiers.succeeded) Successfully deleted persistent history before \(date)")
+                debug(.coreData, "\(DebuggingIdentifiers.succeeded) Successfully deleted persistent history before \(date)")
             } catch {
             } catch {
-                debugPrint(
+                debug(
+                    .coreData,
                     "\(DebuggingIdentifiers.failed) Failed to delete persistent history before \(date): \(error.localizedDescription)"
                     "\(DebuggingIdentifiers.failed) Failed to delete persistent history before \(date): \(error.localizedDescription)"
                 )
                 )
             }
             }
         }
         }
     }
     }
+
+    func initializeStack() throws {
+        // Force initialization of persistent container
+        let container = persistentContainer
+
+        // Verify the store is loaded
+        guard container.persistentStoreCoordinator.persistentStores.isEmpty == false else {
+            throw CoreDataError.storeNotInitializedError(function: #function, file: #file)
+        }
+    }
 }
 }
 
 
 // MARK: - Delete
 // MARK: - Delete
@@ -192,7 +203,7 @@ extension CoreDataStack {
     ///  - Tag: synchronousDelete
     ///  - Tag: synchronousDelete
     func deleteObject(identifiedBy objectID: NSManagedObjectID) async {
     func deleteObject(identifiedBy objectID: NSManagedObjectID) async {
         let viewContext = persistentContainer.viewContext
         let viewContext = persistentContainer.viewContext
-        debugPrint("Start deleting data from the store ...\(DebuggingIdentifiers.inProgress)")
+        debug(.coreData, "Start deleting data from the store ...\(DebuggingIdentifiers.inProgress)")
 
 
         await viewContext.perform {
         await viewContext.perform {
             do {
             do {
@@ -201,9 +212,9 @@ extension CoreDataStack {
 
 
                 guard viewContext.hasChanges else { return }
                 guard viewContext.hasChanges else { return }
                 try viewContext.save()
                 try viewContext.save()
-                debugPrint("Successfully deleted data. \(DebuggingIdentifiers.succeeded)")
+                debug(.coreData, "Successfully deleted data. \(DebuggingIdentifiers.succeeded)")
             } catch {
             } catch {
-                debugPrint("Failed to delete data: \(error.localizedDescription)")
+                debug(.coreData, "Failed to delete data: \(error.localizedDescription)")
             }
             }
         }
         }
     }
     }
@@ -244,7 +255,7 @@ extension CoreDataStack {
 
 
             // Guard check if there are NSManagedObjects older than the specified days
             // Guard check if there are NSManagedObjects older than the specified days
             guard !objectIDs.isEmpty else {
             guard !objectIDs.isEmpty else {
-//                debugPrint("No objects found older than \(days) days.")
+//                debug(.coreData,"No objects found older than \(days) days.")
                 return
                 return
             }
             }
 
 
@@ -255,14 +266,14 @@ extension CoreDataStack {
                       let batchDeleteResult = fetchResult as? NSBatchDeleteResult,
                       let batchDeleteResult = fetchResult as? NSBatchDeleteResult,
                       let success = batchDeleteResult.result as? Bool, success
                       let success = batchDeleteResult.result as? Bool, success
                 else {
                 else {
-                    debugPrint("Failed to execute batch delete request \(DebuggingIdentifiers.failed)")
+                    debug(.coreData, "Failed to execute batch delete request \(DebuggingIdentifiers.failed)")
                     throw CoreDataError.batchDeleteError(function: callingFunction, file: callingClass)
                     throw CoreDataError.batchDeleteError(function: callingFunction, file: callingClass)
                 }
                 }
             }
             }
 
 
-            debugPrint("Successfully deleted data older than \(days) days. \(DebuggingIdentifiers.succeeded)")
+            debug(.coreData, "Successfully deleted data older than \(days) days. \(DebuggingIdentifiers.succeeded)")
         } catch {
         } catch {
-            debugPrint("Failed to fetch or delete data: \(error.localizedDescription) \(DebuggingIdentifiers.failed)")
+            debug(.coreData, "Failed to fetch or delete data: \(error.localizedDescription) \(DebuggingIdentifiers.failed)")
             throw CoreDataError.unexpectedError(error: error, function: callingFunction, file: callingClass)
             throw CoreDataError.unexpectedError(error: error, function: callingFunction, file: callingClass)
         }
         }
     }
     }
@@ -294,7 +305,7 @@ extension CoreDataStack {
             }
             }
 
 
             guard !parentObjectIDs.isEmpty else {
             guard !parentObjectIDs.isEmpty else {
-//                debugPrint("No \(parentType) objects found older than \(days) days.")
+//                debug(.coreData,"No \(parentType) objects found older than \(days) days.")
                 return
                 return
             }
             }
 
 
@@ -308,7 +319,7 @@ extension CoreDataStack {
             }
             }
 
 
             guard !childObjectIDs.isEmpty else {
             guard !childObjectIDs.isEmpty else {
-//                debugPrint("No \(childType) objects found related to \(parentType) objects older than \(days) days.")
+//                debug(.coreData,"No \(childType) objects found related to \(parentType) objects older than \(days) days.")
                 return
                 return
             }
             }
 
 
@@ -319,16 +330,17 @@ extension CoreDataStack {
                       let batchDeleteResult = fetchResult as? NSBatchDeleteResult,
                       let batchDeleteResult = fetchResult as? NSBatchDeleteResult,
                       let success = batchDeleteResult.result as? Bool, success
                       let success = batchDeleteResult.result as? Bool, success
                 else {
                 else {
-                    debugPrint("Failed to execute batch delete request \(DebuggingIdentifiers.failed)")
+                    debug(.coreData, "Failed to execute batch delete request \(DebuggingIdentifiers.failed)")
                     throw CoreDataError.batchDeleteError(function: callingFunction, file: callingClass)
                     throw CoreDataError.batchDeleteError(function: callingFunction, file: callingClass)
                 }
                 }
             }
             }
 
 
-            debugPrint(
+            debug(
+                .coreData,
                 "Successfully deleted \(childType) data related to \(parentType) objects older than \(days) days. \(DebuggingIdentifiers.succeeded)"
                 "Successfully deleted \(childType) data related to \(parentType) objects older than \(days) days. \(DebuggingIdentifiers.succeeded)"
             )
             )
         } catch {
         } catch {
-            debugPrint("Failed to fetch or delete data: \(error.localizedDescription) \(DebuggingIdentifiers.failed)")
+            debug(.coreData, "Failed to fetch or delete data: \(error.localizedDescription) \(DebuggingIdentifiers.failed)")
             throw CoreDataError.unexpectedError(error: error, function: callingFunction, file: callingClass)
             throw CoreDataError.unexpectedError(error: error, function: callingFunction, file: callingClass)
         }
         }
     }
     }
@@ -479,7 +491,7 @@ extension CoreDataStack {
         do {
         do {
             try context.save()
             try context.save()
         } catch {
         } catch {
-            debugPrint("Error saving context \(DebuggingIdentifiers.failed): \(error)")
+            debug(.coreData, "Error saving context \(DebuggingIdentifiers.failed): \(error)")
         }
         }
     }
     }
 }
 }
@@ -495,11 +507,12 @@ extension NSManagedObjectContext {
         do {
         do {
             guard onContext.hasChanges else { return }
             guard onContext.hasChanges else { return }
             try onContext.save()
             try onContext.save()
-//            debugPrint(
+//            debug(.coreData,
 //                "Saving to Core Data successful in \(callingFunction) in \(callingClass): \(DebuggingIdentifiers.succeeded)"
 //                "Saving to Core Data successful in \(callingFunction) in \(callingClass): \(DebuggingIdentifiers.succeeded)"
 //            )
 //            )
         } catch let error as NSError {
         } catch let error as NSError {
-            debugPrint(
+            debug(
+                .coreData,
                 "Saving to Core Data failed in \(callingFunction) in \(callingClass): \(DebuggingIdentifiers.failed) with error \(error), \(error.userInfo)"
                 "Saving to Core Data failed in \(callingFunction) in \(callingClass): \(DebuggingIdentifiers.failed) with error \(error), \(error.userInfo)"
             )
             )
             throw error
             throw error

+ 6 - 0
Model/Helper/CoreDataError.swift

@@ -8,6 +8,7 @@ enum CoreDataError: Error {
     case persistentHistoryChangeError(function: String, file: String)
     case persistentHistoryChangeError(function: String, file: String)
     case unexpectedError(error: Error, function: String, file: String)
     case unexpectedError(error: Error, function: String, file: String)
     case fetchError(function: String, file: String)
     case fetchError(function: String, file: String)
+    case storeNotInitializedError(function: String, file: String)
 }
 }
 
 
 extension CoreDataError: LocalizedError {
 extension CoreDataError: LocalizedError {
@@ -36,6 +37,11 @@ extension CoreDataError: LocalizedError {
             )
             )
         case let .validationError(function, file):
         case let .validationError(function, file):
             return NSLocalizedString("Failed to validate object in \(function) from \(file).", comment: "")
             return NSLocalizedString("Failed to validate object in \(function) from \(file).", comment: "")
+        case let .storeNotInitializedError(function, file):
+            return NSLocalizedString(
+                "Store not initialized in \(function) from \(file).",
+                comment: ""
+            )
         }
         }
     }
     }
 }
 }

+ 22 - 10
Trio/Sources/Application/TrioApp.swift

@@ -13,7 +13,7 @@ import Swinject
     // Read the color scheme preference from UserDefaults; defaults to system default setting
     // Read the color scheme preference from UserDefaults; defaults to system default setting
     @AppStorage("colorSchemePreference") private var colorSchemePreference: ColorSchemeOption = .systemDefault
     @AppStorage("colorSchemePreference") private var colorSchemePreference: ColorSchemeOption = .systemDefault
 
 
-    let coreDataStack = CoreDataStack.shared
+    let coreDataStack: CoreDataStack
 
 
     @State private var appState = AppState()
     @State private var appState = AppState()
 
 
@@ -68,14 +68,26 @@ import Swinject
             "Trio Started: v\(Bundle.main.releaseVersionNumber ?? "")(\(Bundle.main.buildVersionNumber ?? "")) [buildDate: \(String(describing: BuildDetails.default.buildDate()))] [buildExpires: \(String(describing: BuildDetails.default.calculateExpirationDate()))]"
             "Trio Started: v\(Bundle.main.releaseVersionNumber ?? "")(\(Bundle.main.buildVersionNumber ?? "")) [buildDate: \(String(describing: BuildDetails.default.buildDate()))] [buildExpires: \(String(describing: BuildDetails.default.calculateExpirationDate()))]"
         )
         )
 
 
-        // Load services
-        loadServices()
+        // Initialize Core Data Stack
+        coreDataStack = CoreDataStack.shared
 
 
-        // Fix bug in iOS 18 related to the translucent tab bar
-        configureTabBarAppearance()
+        // Explicitly initialize Core Data Stack
+        do {
+            try coreDataStack.initializeStack()
+
+            // Only load services after successful Core Data initialization
+            loadServices()
+
+            // Fix bug in iOS 18 related to the translucent tab bar
+            configureTabBarAppearance()
+            
+            // Clear the persistentHistory and the NSManagedObjects that are older than 90 days every time the app starts
+            cleanupOldData()
+        } catch {
+            debug(.coreData, "\(DebuggingIdentifiers.failed) Failed to initialize Core Data Stack: \(error.localizedDescription)")
 
 
-        // Clear the persistentHistory and the NSManagedObjects that are older than 90 days every time the app starts
-        cleanupOldData()
+            fatalError("Core Data Stack initialization failed")
+        }
     }
     }
 
 
     var body: some Scene {
     var body: some Scene {
@@ -127,9 +139,9 @@ import Swinject
         request.earliestBeginDate = .now.addingTimeInterval(7 * 24 * 60 * 60) // 7 days
         request.earliestBeginDate = .now.addingTimeInterval(7 * 24 * 60 * 60) // 7 days
         do {
         do {
             try BGTaskScheduler.shared.submit(request)
             try BGTaskScheduler.shared.submit(request)
-            debugPrint("Task scheduled successfully")
-        } catch {
-            debugPrint("Failed to schedule tasks")
+            debug(.coreData, "Task for cleaning database scheduled successfully")
+        } catch let error {
+            debug(.coreData, "Failed to schedule tasks for cleaning database: \(error.localizedDescription)")
         }
         }
     }
     }
 
 

+ 4 - 0
Trio/Sources/Logger/Logger.swift

@@ -115,6 +115,7 @@ final class Logger {
     static let remoteControl = Logger(category: .remoteControl, reporter: baseReporter)
     static let remoteControl = Logger(category: .remoteControl, reporter: baseReporter)
     static let bolusState = Logger(category: .bolusState, reporter: baseReporter)
     static let bolusState = Logger(category: .bolusState, reporter: baseReporter)
     static let watchManager = Logger(category: .watchManager, reporter: baseReporter)
     static let watchManager = Logger(category: .watchManager, reporter: baseReporter)
+    static let coreData = Logger(category: .coreData, reporter: baseReporter)
 
 
     enum Category: String {
     enum Category: String {
         case `default`
         case `default`
@@ -127,6 +128,7 @@ final class Logger {
         case remoteControl
         case remoteControl
         case bolusState
         case bolusState
         case watchManager
         case watchManager
+        case coreData
 
 
         var name: String {
         var name: String {
             rawValue.capitalizingFirstLetter()
             rawValue.capitalizingFirstLetter()
@@ -144,6 +146,7 @@ final class Logger {
             case .remoteControl: return .remoteControl
             case .remoteControl: return .remoteControl
             case .bolusState: return .bolusState
             case .bolusState: return .bolusState
             case .watchManager: return .watchManager
             case .watchManager: return .watchManager
+            case .coreData: return .coreData
             }
             }
         }
         }
 
 
@@ -154,6 +157,7 @@ final class Logger {
             case .apsManager,
             case .apsManager,
                  .bolusState,
                  .bolusState,
                  .businessLogic,
                  .businessLogic,
+                 .coreData,
                  .deviceManager,
                  .deviceManager,
                  .nightscout,
                  .nightscout,
                  .openAPS,
                  .openAPS,