Explorar el Código

Re-anchor Home FRC fetch windows when entering foreground

Marvin Polscheit hace 17 horas
padre
commit
264148c397

+ 6 - 0
Model/Helper/NSPredicates.swift

@@ -66,6 +66,12 @@ extension NSPredicate {
         return NSPredicate(format: "date >= %@", date as NSDate)
     }
 
+    /// For entities keyed on `startDate` (OverrideRunStored, TempTargetRunStored).
+    static var predicateForStartDateOneDayAgo: NSPredicate {
+        let date = Date.oneDayAgo
+        return NSPredicate(format: "startDate >= %@", date as NSDate)
+    }
+
     static var carbsHistory: NSPredicate {
         let date = Date.oneDayAgo
         return NSPredicate(format: "date >= %@ AND carbs > 0", date as NSDate)

+ 1 - 1
Trio/Sources/Modules/Home/HomeStateModel+Setup/BatterySetup.swift

@@ -17,7 +17,7 @@ extension Home.StateModel {
         }
     }
 
-    @MainActor private func updateBatteryFromController() {
+    @MainActor func updateBatteryFromController() {
         guard let objects = batteryController.fetchedObjects else { return }
         batteryFromPersistence = objects
     }

+ 2 - 2
Trio/Sources/Modules/Home/HomeStateModel+Setup/CarbSetup.swift

@@ -19,7 +19,7 @@ extension Home.StateModel {
         }
     }
 
-    @MainActor private func updateCarbsFromController() {
+    @MainActor func updateCarbsFromController() {
         guard let objects = carbsController.fetchedObjects else { return }
         carbsFromPersistence = objects
     }
@@ -41,7 +41,7 @@ extension Home.StateModel {
         }
     }
 
-    @MainActor private func updateFPUsFromController() {
+    @MainActor func updateFPUsFromController() {
         guard let objects = fpuController.fetchedObjects else { return }
         fpusFromPersistence = objects
     }

+ 1 - 1
Trio/Sources/Modules/Home/HomeStateModel+Setup/DeterminationSetup.swift

@@ -46,7 +46,7 @@ extension Home.StateModel {
         }
     }
 
-    @MainActor private func updateDeterminationsFromController() {
+    @MainActor func updateDeterminationsFromController() {
         guard let objects = determinationController.fetchedObjects else { return }
         enactedAndNonEnactedDeterminations = objects
         yAxisChartDataCobChart(determinations: objects)

+ 1 - 1
Trio/Sources/Modules/Home/HomeStateModel+Setup/OverrideSetup.swift

@@ -41,7 +41,7 @@ extension Home.StateModel {
         }
     }
 
-    @MainActor private func updateOverrideRunsFromController() {
+    @MainActor func updateOverrideRunsFromController() {
         guard let objects = overrideRunController.fetchedObjects else { return }
         overrideRunStored = objects
     }

+ 1 - 1
Trio/Sources/Modules/Home/HomeStateModel+Setup/PumpHistorySetup.swift

@@ -22,7 +22,7 @@ extension Home.StateModel {
         }
     }
 
-    @MainActor private func updateInsulinFromController() {
+    @MainActor func updateInsulinFromController() {
         guard let objects = insulinController.fetchedObjects else { return }
         insulinFromPersistence = objects
 

+ 1 - 1
Trio/Sources/Modules/Home/HomeStateModel+Setup/TempTargetSetup.swift

@@ -41,7 +41,7 @@ extension Home.StateModel {
         }
     }
 
-    @MainActor private func updateTempTargetRunsFromController() {
+    @MainActor func updateTempTargetRunsFromController() {
         guard let objects = tempTargetRunController.fetchedObjects else { return }
         tempTargetRunStored = objects
     }

+ 44 - 2
Trio/Sources/Modules/Home/HomeStateModel.swift

@@ -281,7 +281,7 @@ extension Home {
         @ObservationIgnored private(set) lazy var overrideRunController: NSFetchedResultsController<OverrideRunStored> = {
             let request = NSFetchRequest<OverrideRunStored>(entityName: "OverrideRunStored")
             request.sortDescriptors = [NSSortDescriptor(keyPath: \OverrideRunStored.startDate, ascending: false)]
-            request.predicate = NSPredicate(format: "startDate >= %@", Date.oneDayAgo as NSDate)
+            request.predicate = NSPredicate.predicateForStartDateOneDayAgo
             let controller = NSFetchedResultsController(
                 fetchRequest: request,
                 managedObjectContext: viewContext,
@@ -311,7 +311,7 @@ extension Home {
         @ObservationIgnored private(set) lazy var tempTargetRunController: NSFetchedResultsController<TempTargetRunStored> = {
             let request = NSFetchRequest<TempTargetRunStored>(entityName: "TempTargetRunStored")
             request.sortDescriptors = [NSSortDescriptor(keyPath: \TempTargetRunStored.startDate, ascending: false)]
-            request.predicate = NSPredicate(format: "startDate >= %@", Date.oneDayAgo as NSDate)
+            request.predicate = NSPredicate.predicateForStartDateOneDayAgo
             let controller = NSFetchedResultsController(
                 fetchRequest: request,
                 managedObjectContext: viewContext,
@@ -353,6 +353,40 @@ extension Home {
             return controller
         }()
 
+        // MARK: - Fetch window re-anchoring
+
+        /// Called on `UIApplication.willEnterForegroundNotification`
+        @MainActor func reanchorFetchWindows() {
+            reanchor(glucoseController, with: NSPredicate.glucose) { self.updateGlucoseFromController() }
+            reanchor(carbsController, with: NSPredicate.carbsForChart) { self.updateCarbsFromController() }
+            reanchor(fpuController, with: NSPredicate.fpusForChart) { self.updateFPUsFromController() }
+            reanchor(determinationController, with: NSPredicate.determinationsForCobIobCharts) {
+                self.updateDeterminationsFromController()
+            }
+            reanchor(insulinController, with: NSPredicate.pumpHistoryLast24h) { self.updateInsulinFromController() }
+            reanchor(overrideRunController, with: NSPredicate.predicateForStartDateOneDayAgo) {
+                self.updateOverrideRunsFromController()
+            }
+            reanchor(tempTargetRunController, with: NSPredicate.predicateForStartDateOneDayAgo) {
+                self.updateTempTargetRunsFromController()
+            }
+            reanchor(batteryController, with: NSPredicate.predicateFor30MinAgo) { self.updateBatteryFromController() }
+        }
+
+        @MainActor private func reanchor<T: NSFetchRequestResult>(
+            _ controller: NSFetchedResultsController<T>,
+            with predicate: NSPredicate,
+            republish: () -> Void
+        ) {
+            controller.fetchRequest.predicate = predicate
+            do {
+                try controller.performFetch()
+                republish()
+            } catch {
+                debug(.default, "\(DebuggingIdentifiers.failed) Failed to re-anchor fetch window for \(T.self): \(error)")
+            }
+        }
+
         private var subscriptions = Set<AnyCancellable>()
 
         typealias PumpEvent = PumpEventStored.EventType
@@ -483,6 +517,14 @@ extension Home {
             }
             timer.resume()
 
+            Foundation.NotificationCenter.default.publisher(for: UIApplication.willEnterForegroundNotification)
+                .sink { [weak self] _ in
+                    Task { @MainActor in
+                        self?.reanchorFetchWindows()
+                    }
+                }
+                .store(in: &lifetime)
+
             fetchGlucoseManager.cgmDisplayState
                 .receive(on: DispatchQueue.main)
                 .sink { [weak self] state in self?.cgmDisplayState = state }