Bläddra i källkod

Add back performCleanupIfNecessary and add docstrings

Sam King 1 år sedan
förälder
incheckning
4b5173016d

+ 7 - 0
Model/CoreDataInitializationCoordinator.swift

@@ -4,6 +4,13 @@ actor CoreDataInitializationCoordinator {
     private var isInitialized = false
     private var initializationTask: Task<Void, Error>?
 
+    /// Ensures that initialization only happens once and manages multiple concurrent initialization requests.
+    /// This actor provides synchronization for the CoreDataStack initialization process.
+    ///
+    /// - Parameters:
+    ///   - initialization: A closure that performs the actual initialization work.
+    /// - Throws: Any error that might occur during initialization.
+    /// - Returns: Void once initialization is complete.
     func ensureInitialized(perform initialization: @escaping () async throws -> Void) async throws {
         // If already initialized, return immediately
         if isInitialized {

+ 24 - 1
Model/CoreDataStack.swift

@@ -182,7 +182,14 @@ class CoreDataStack: ObservableObject {
 
         debug(.coreData, "Set up persistent store change notifications")
     }
-
+    
+    /// Loads the persistent stores asynchronously.
+    ///
+    /// Converts the synchronous NSPersistentContainer loading process into an async/await compatible
+    /// function using a continuation.
+    ///
+    /// - Throws: Any errors encountered during the loading of persistent stores.
+    /// - Returns: Void once stores are loaded successfully
     private func loadPersistentStores() async throws {
         try await withCheckedThrowingContinuation { (continuation: CheckedContinuation<Void, Error>) in
             persistentContainer.loadPersistentStores { storeDescription, error in
@@ -197,12 +204,28 @@ class CoreDataStack: ObservableObject {
         }
     }
 
+    /// Public entry point for initializing the CoreData stack.
+    ///
+    /// Uses the initialization coordinator to ensure initialization happens only once,
+    /// even with concurrent calls. Subsequent calls will wait for the original initialization
+    /// to complete.
+    ///
+    /// - Throws: Any errors that occur during initialization.
+    /// - Returns: Void once initialization is complete.
     func initializeStack() async throws {
         try await initializationCoordinator.ensureInitialized {
             try await self.initializeStack(retryCount: 0)
         }
     }
 
+    /// Private implementation of the initialization process with retry capability.
+    ///
+    /// Handles the actual initialization work including store loading, verification,
+    /// notification setup, and error handling with retry logic.
+    ///
+    /// - Parameter retryCount: The current retry attempt number, starting at 0.
+    /// - Throws: CoreDataError or any other error if initialization fails after all retries.
+    /// - Returns: Void when initialization completes successfully.
     private func initializeStack(retryCount: Int) async throws {
         do {
             // Load stores asynchronously

+ 15 - 0
Trio/Sources/Application/TrioApp.swift

@@ -24,6 +24,10 @@ extension Notification.Name {
         var error = false
     }
 
+    // We use both InitState and @State variables to track coreDataStack
+    // initialization. We need both to handle the cases when the coreDataStack
+    // finishes before the UI and when it finishes after. SwiftUI doesn't have
+    // clean mechanisms for handling background thread updates, thus this solution.
     let initState = InitState()
 
     @State private var appState = AppState()
@@ -91,6 +95,10 @@ extension Notification.Name {
         deferredInitialization()
     }
 
+    /// Handles the deferred initialization of core components.
+    ///
+    /// Performs CoreDataStack initialization asynchronously and notifies the UI
+    /// of completion or errors via notifications.
     private func deferredInitialization() {
         Task {
             do {
@@ -121,6 +129,10 @@ extension Notification.Name {
         }
     }
 
+    /// Attempts to initialize the CoreDataStack again after a previous failure.
+    ///
+    /// Resets error states and triggers the initialization process from the beginning. Called in response
+    /// to a UI "retry" button press from the Main.LoadingView
     private func retryCoreDataInitialization() {
         showLoadingError = false
         initState.error = false
@@ -169,6 +181,9 @@ extension Notification.Name {
                 {
                     AppVersionChecker.shared.checkAndNotifyVersionStatus(in: rootVC)
                 }
+                if initState.complete {
+                    performCleanupIfNecessary()
+                }
             }
         }
     }

+ 9 - 0
Trio/Sources/Localizations/Main/Localizable.xcstrings

@@ -129263,6 +129263,9 @@
         }
       }
     },
+    "Oops, there was an issue!" : {
+
+    },
     "Open %@" : {
       "localizations" : {
         "bg" : {
@@ -142725,6 +142728,9 @@
         }
       }
     },
+    "Retry" : {
+
+    },
     "Return to Normal" : {
       "extractionState" : "manual",
       "localizations" : {
@@ -183135,6 +183141,9 @@
     "Trio Up-Time Chart" : {
 
     },
+    "Trio v%@" : {
+
+    },
     "Trio v%@ (%@)" : {
       "localizations" : {
         "bg" : {