Explorar el Código

Explicitly force core data stack initialization to avoid crashes; don't just rely on persistent container lazy loading

Co-Authored-By: marv-out <marv-out@users.noreply.github.com>
Deniz Cengiz hace 1 año
padre
commit
4cd23434e6

+ 12 - 2
Model/CoreDataStack.swift

@@ -105,7 +105,7 @@ class CoreDataStack: ObservableObject {
     private func fetchPersistentHistoryTransactionsAndChanges() async throws {
         let taskContext = newTaskContext()
         taskContext.name = "persistentHistoryContext"
-//        debugPrint("Start fetching persistent history changes from the store ... \(DebuggingIdentifiers.inProgress)")
+        //        debugPrint("Start fetching persistent history changes from the store ... \(DebuggingIdentifiers.inProgress)")
 
         try await taskContext.perform {
             // Execute the persistent history change since the last transaction
@@ -120,7 +120,7 @@ class CoreDataStack: ObservableObject {
     }
 
     private func mergePersistentHistoryChanges(from history: [NSPersistentHistoryTransaction]) {
-//        debugPrint("Received \(history.count) persistent history transactions")
+        //        debugPrint("Received \(history.count) persistent history transactions")
         // Update view context with objectIDs from history change request
         /// - Tag: mergeChanges
         let viewContext = persistentContainer.viewContext
@@ -150,6 +150,16 @@ class CoreDataStack: ObservableObject {
             }
         }
     }
+
+    func initializeStack() throws {
+        // Force initialization of persistent container
+        let container = persistentContainer
+
+        // Verify the store is loaded and available
+        guard container.persistentStoreCoordinator.persistentStores.isNotEmpty else {
+            throw CoreDataError.storeNotInitializedError
+        }
+    }
 }
 
 // MARK: - Delete

+ 3 - 0
Model/Helper/CoreDataError.swift

@@ -7,6 +7,7 @@ enum CoreDataError: Error {
     case persistentHistoryChangeError
     case unexpectedError(error: Error)
     case fetchError
+    case storeNotInitializedError
 }
 
 extension CoreDataError: LocalizedError {
@@ -24,6 +25,8 @@ extension CoreDataError: LocalizedError {
             return NSLocalizedString("Received unexpected error. \(error.localizedDescription)", comment: "")
         case .fetchError:
             return NSLocalizedString("Failed to fetch object \(DebuggingIdentifiers.failed).", comment: "")
+        case .storeNotInitializedError:
+            return NSLocalizedString("Failed to initialize Core Data's persistent store.", comment: "")
         }
     }
 }

+ 24 - 9
Trio/Sources/Application/TrioApp.swift

@@ -13,7 +13,7 @@ import Swinject
     // Read the color scheme preference from UserDefaults; defaults to system default setting
     @AppStorage("colorSchemePreference") private var colorSchemePreference: ColorSchemeOption = .systemDefault
 
-    let coreDataStack = CoreDataStack.shared
+    let coreDataStack: CoreDataStack
 
     @State private var appState = AppState()
 
@@ -67,15 +67,30 @@ import Swinject
             .default,
             "Trio Started: v\(Bundle.main.releaseVersionNumber ?? "")(\(Bundle.main.buildVersionNumber ?? "")) [buildDate: \(String(describing: BuildDetails.default.buildDate()))] [buildExpires: \(String(describing: BuildDetails.default.calculateExpirationDate()))]"
         )
+        
+        // Setup up the Core Data Stack
+        coreDataStack = CoreDataStack.shared
 
-        // Load services
-        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()
+        do {
+            // Explicitly initialize Core Data Stacak
+            try coreDataStack.initializeStack()
+            
+            // Load services
+            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,
+                "Failed to initialize Core Data Stack: \(error.localizedDescription)"
+            )
+            // Handle initialization failure
+            fatalError("Core Data Stack initialization failed: \(error.localizedDescription)")
+        }
     }
 
     var body: some Scene {

+ 5 - 1
Trio/Sources/Logger/Logger.swift

@@ -115,6 +115,7 @@ final class Logger {
     static let remoteControl = Logger(category: .remoteControl, reporter: baseReporter)
     static let bolusState = Logger(category: .bolusState, reporter: baseReporter)
     static let watchManager = Logger(category: .watchManager, reporter: baseReporter)
+    static let coreData = Logger(category: .coreData, reporter: baseReporter)
 
     enum Category: String {
         case `default`
@@ -127,6 +128,7 @@ final class Logger {
         case remoteControl
         case bolusState
         case watchManager
+        case coreData
 
         var name: String {
             rawValue.capitalizingFirstLetter()
@@ -144,6 +146,7 @@ final class Logger {
             case .remoteControl: return .remoteControl
             case .bolusState: return .bolusState
             case .watchManager: return .watchManager
+            case .coreData: return .coreData
             }
         }
 
@@ -159,7 +162,8 @@ final class Logger {
                  .openAPS,
                  .remoteControl,
                  .service,
-                 .watchManager:
+                 .watchManager,
+                 .coreData:
                 return OSLog(subsystem: subsystem, category: name)
             }
         }