Browse Source

fix for LA updating, clean up

polscm32 2 years ago
parent
commit
3358be3731
1 changed files with 58 additions and 32 deletions
  1. 58 32
      FreeAPS/Sources/Services/LiveActivity/LiveActivityBridge.swift

+ 58 - 32
FreeAPS/Sources/Services/LiveActivity/LiveActivityBridge.swift

@@ -1,4 +1,5 @@
 import ActivityKit
 import ActivityKit
+import CoreData
 import Foundation
 import Foundation
 import Swinject
 import Swinject
 import UIKit
 import UIKit
@@ -123,7 +124,9 @@ extension LiveActivityAttributes.ContentState {
     }
     }
 }
 }
 
 
-@available(iOS 16.2, *) final class LiveActivityBridge: Injectable, ObservableObject {
+@available(iOS 16.2, *) final class LiveActivityBridge: NSObject, Injectable, ObservableObject,
+    NSFetchedResultsControllerDelegate
+{
     @Injected() private var settingsManager: SettingsManager!
     @Injected() private var settingsManager: SettingsManager!
     @Injected() private var broadcaster: Broadcaster!
     @Injected() private var broadcaster: Broadcaster!
     @Injected() private var storage: FileStorage!
     @Injected() private var storage: FileStorage!
@@ -138,30 +141,59 @@ extension LiveActivityAttributes.ContentState {
     private var determination: OrefDetermination?
     private var determination: OrefDetermination?
     private var currentActivity: ActiveActivity?
     private var currentActivity: ActiveActivity?
     private var latestGlucose: GlucoseStored?
     private var latestGlucose: GlucoseStored?
+    private var fetchedResultsController: NSFetchedResultsController<GlucoseStored>?
 
 
     init(resolver: Resolver) {
     init(resolver: Resolver) {
         systemEnabled = activityAuthorizationInfo.areActivitiesEnabled
         systemEnabled = activityAuthorizationInfo.areActivitiesEnabled
+        super.init()
+
         injectServices(resolver)
         injectServices(resolver)
-        broadcaster.register(GlucoseStoredObserver.self, observer: self)
+        setupNotifications()
+        monitorForLiveActivityAuthorizationChanges()
+        initializeFetchedResultsController()
+    }
 
 
+    private func setupNotifications() {
         Foundation.NotificationCenter.default.addObserver(
         Foundation.NotificationCenter.default.addObserver(
             forName: UIApplication.didEnterBackgroundNotification,
             forName: UIApplication.didEnterBackgroundNotification,
             object: nil,
             object: nil,
             queue: nil
             queue: nil
-        ) { _ in
-            self.forceActivityUpdate()
+        ) { [weak self] _ in
+            self?.forceActivityUpdate()
         }
         }
 
 
         Foundation.NotificationCenter.default.addObserver(
         Foundation.NotificationCenter.default.addObserver(
             forName: UIApplication.didBecomeActiveNotification,
             forName: UIApplication.didBecomeActiveNotification,
             object: nil,
             object: nil,
             queue: nil
             queue: nil
-        ) { _ in
-            self.forceActivityUpdate()
+        ) { [weak self] _ in
+            self?.forceActivityUpdate()
         }
         }
+    }
 
 
-        monitorForLiveActivityAuthorizationChanges()
-        determination = fetchDetermination()
+    private func initializeFetchedResultsController() {
+        let fetchRequest: NSFetchRequest<GlucoseStored> = GlucoseStored.fetchRequest()
+        fetchRequest.sortDescriptors = [NSSortDescriptor(key: "date", ascending: false)]
+        fetchRequest.fetchLimit = 72
+        fetchRequest.predicate = NSPredicate.predicateForSixHoursAgo
+
+        fetchedResultsController = NSFetchedResultsController(
+            fetchRequest: fetchRequest,
+            managedObjectContext: CoreDataStack.shared.viewContext,
+            sectionNameKeyPath: nil,
+            cacheName: nil
+        )
+        fetchedResultsController?.delegate = self
+
+        do {
+            try fetchedResultsController?.performFetch()
+            debugPrint(
+                "LA Bridge: \(#function) \(CoreDataStack.identifier) \(DebuggingIdentifiers.succeeded) fetched glucose"
+            )
+        } catch {
+            debugPrint(
+                "LA Bridge: \(#function) \(CoreDataStack.identifier) \(DebuggingIdentifiers.failed) failed to fetch glucose"
+            ) }
     }
     }
 
 
     private func monitorForLiveActivityAuthorizationChanges() {
     private func monitorForLiveActivityAuthorizationChanges() {
@@ -199,7 +231,9 @@ extension LiveActivityAttributes.ContentState {
         if settings.useLiveActivity {
         if settings.useLiveActivity {
             if currentActivity?.needsRecreation() ?? true
             if currentActivity?.needsRecreation() ?? true
             {
             {
-                glucoseDidUpdate(fetchGlucose())
+                if let glucoseRecords = fetchedResultsController?.fetchedObjects as? [GlucoseStored] {
+                    glucoseDidUpdate(glucoseRecords)
+                }
             }
             }
         } else {
         } else {
             Task {
             Task {
@@ -283,7 +317,18 @@ extension LiveActivityAttributes.ContentState {
 }
 }
 
 
 @available(iOS 16.2, *)
 @available(iOS 16.2, *)
-extension LiveActivityBridge: GlucoseStoredObserver {
+extension LiveActivityBridge {
+    func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
+        guard let glucoseChanges = controller.fetchedObjects as? [GlucoseStored] else {
+            return
+        }
+
+        glucoseDidUpdate(glucoseChanges)
+    }
+}
+
+@available(iOS 16.2, *)
+extension LiveActivityBridge {
     func glucoseDidUpdate(_ glucose: [GlucoseStored]) {
     func glucoseDidUpdate(_ glucose: [GlucoseStored]) {
         guard settings.useLiveActivity else {
         guard settings.useLiveActivity else {
             if currentActivity != nil {
             if currentActivity != nil {
@@ -302,19 +347,18 @@ extension LiveActivityBridge: GlucoseStoredObserver {
             self.latestGlucose = glucose.first
             self.latestGlucose = glucose.first
         }
         }
 
 
-        // fetch glucose for the last 6 hours for the LA chart from Core Data
-        let fetchedGlucose = fetchGlucose()
-
         guard let bg = glucose.first else {
         guard let bg = glucose.first else {
             return
             return
         }
         }
 
 
+        determination = fetchDetermination()
+
         if let determination = determination {
         if let determination = determination {
             let content = LiveActivityAttributes.ContentState(
             let content = LiveActivityAttributes.ContentState(
                 new: bg,
                 new: bg,
                 prev: latestGlucose,
                 prev: latestGlucose,
                 mmol: settings.units == .mmolL,
                 mmol: settings.units == .mmolL,
-                chart: fetchedGlucose,
+                chart: glucose,
                 settings: settings,
                 settings: settings,
                 determination: determination
                 determination: determination
             )
             )
@@ -326,22 +370,4 @@ extension LiveActivityBridge: GlucoseStoredObserver {
             }
             }
         }
         }
     }
     }
-
-    private func fetchGlucose() -> [GlucoseStored] {
-        let context = CoreDataStack.shared.viewContext
-        do {
-            let fetchedGlucose = try context
-                .fetch(GlucoseStored.fetch(NSPredicate.predicateForSixHoursAgo, ascending: false, fetchLimit: 72))
-            debugPrint(
-                "LA Bridge: \(#function) \(CoreDataStack.identifier) \(DebuggingIdentifiers.succeeded) fetched glucose"
-            )
-
-            return fetchedGlucose
-        } catch {
-            debugPrint(
-                "LA Bridge: \(#function) \(CoreDataStack.identifier) \(DebuggingIdentifiers.failed) failed to fetch glucose"
-            )
-            return []
-        }
-    }
 }
 }