Pārlūkot izejas kodu

only save a context when it has changed

polscm32 2 gadi atpakaļ
vecāks
revīzija
a03074c7a2

+ 31 - 19
FreeAPS/Sources/APS/APSManager.swift

@@ -721,13 +721,17 @@ final class BaseAPSManager: APSManager, Injectable {
             viewContext.perform {
                 determination.timestamp = Date()
                 determination.received = received
-                do {
-                    try self.viewContext.save()
-                    debugPrint("APSManager: \(CoreDataStack.identifier) \(DebuggingIdentifiers.succeeded) updated determination")
-                } catch {
-                    debugPrint(
-                        "APSManager: \(CoreDataStack.identifier) \(DebuggingIdentifiers.failed) failed to update determination"
-                    )
+                if self.viewContext.hasChanges {
+                    do {
+                        try self.viewContext.save()
+                        debugPrint(
+                            "APSManager: \(CoreDataStack.identifier) \(DebuggingIdentifiers.succeeded) updated determination"
+                        )
+                    } catch {
+                        debugPrint(
+                            "APSManager: \(CoreDataStack.identifier) \(DebuggingIdentifiers.failed) failed to update determination"
+                        )
+                    }
                 }
 
                 // parse to determination
@@ -737,7 +741,9 @@ final class BaseAPSManager: APSManager, Injectable {
                 saveLastLoop.iob = (determination.iob ?? 0) as NSDecimalNumber
                 saveLastLoop.cob = determination.cob as? NSDecimalNumber
                 saveLastLoop.timestamp = (determination.timestamp ?? .distantPast) as Date
-                try? self.viewContext.save()
+                if self.viewContext.hasChanges {
+                    try? self.viewContext.save()
+                }
 
                 debug(.apsManager, "Determination enacted. Received: \(received)")
             }
@@ -1228,7 +1234,9 @@ final class BaseAPSManager: APSManager, Injectable {
 
                 let saveStatsCoreData = StatsData(context: self.privateContext)
                 saveStatsCoreData.lastrun = Date()
-                try? self.privateContext.save()
+                if self.privateContext.hasChanges {
+                    try? self.privateContext.save()
+                }
             }
         }
     }
@@ -1243,7 +1251,9 @@ final class BaseAPSManager: APSManager, Injectable {
             nLS.duration = loopStatRecord.duration ?? 0.0
             nLS.interval = loopStatRecord.interval ?? 0.0
 
-            try? self.privateContext.save()
+            if self.privateContext.hasChanges {
+                try? self.privateContext.save()
+            }
         }
     }
 
@@ -1381,15 +1391,17 @@ extension BaseAPSManager: PumpManagerStatusObserver {
         batteryToStore.status = percent > 10 ? "normal" : "low"
         batteryToStore.display = status.pumpBatteryChargeRemaining != nil
         privateContext.perform {
-            do {
-                try self.privateContext.save()
-                debugPrint(
-                    "APS Manager: \(#function) \(CoreDataStack.identifier) \(DebuggingIdentifiers.succeeded) saved battery infos to core data"
-                )
-            } catch {
-                debugPrint(
-                    "APS Manager: \(#function) \(CoreDataStack.identifier) \(DebuggingIdentifiers.failed) failed to save battery infos to core data"
-                )
+            if self.privateContext.hasChanges {
+                do {
+                    try self.privateContext.save()
+                    debugPrint(
+                        "APS Manager: \(#function) \(CoreDataStack.identifier) \(DebuggingIdentifiers.succeeded) saved battery infos to core data"
+                    )
+                } catch {
+                    debugPrint(
+                        "APS Manager: \(#function) \(CoreDataStack.identifier) \(DebuggingIdentifiers.failed) failed to save battery infos to core data"
+                    )
+                }
             }
         }
         storage.save(status.pumpStatus, as: OpenAPS.Monitor.status)

+ 11 - 9
FreeAPS/Sources/APS/DeviceDataManager.swift

@@ -355,15 +355,17 @@ extension BaseDeviceDataManager: PumpManagerDelegate {
         batteryToStore.status = batteryPercent > 10 ? "normal" : "low"
         batteryToStore.display = status.pumpBatteryChargeRemaining != nil
         privateContext.perform {
-            do {
-                try self.privateContext.save()
-                debugPrint(
-                    "Device Data manager: \(#function) \(CoreDataStack.identifier) \(DebuggingIdentifiers.succeeded) saved battery infos to core data"
-                )
-            } catch {
-                debugPrint(
-                    "Device Data manager: \(#function) \(CoreDataStack.identifier) \(DebuggingIdentifiers.failed) failed to save battery infos to core data"
-                )
+            if self.privateContext.hasChanges {
+                do {
+                    try self.privateContext.save()
+                    debugPrint(
+                        "Device Data manager: \(#function) \(CoreDataStack.identifier) \(DebuggingIdentifiers.succeeded) saved battery infos to core data"
+                    )
+                } catch {
+                    debugPrint(
+                        "Device Data manager: \(#function) \(CoreDataStack.identifier) \(DebuggingIdentifiers.failed) failed to save battery infos to core data"
+                    )
+                }
             }
         }
         broadcaster.notify(PumpTimeZoneObserver.self, on: processQueue) {

+ 27 - 27
FreeAPS/Sources/APS/OpenAPS/OpenAPS.swift

@@ -139,15 +139,18 @@ final class OpenAPS {
                         newOrefDetermination.bolus = determination.insulin?.bolus as? NSDecimalNumber
                         newOrefDetermination.smbToDeliver = determination.units as? NSDecimalNumber
                         newOrefDetermination.carbsRequired = Int16(Int(determination.carbsReq ?? 0))
-                        do {
-                            try self.context.save()
-                            debugPrint(
-                                "OpenAPS: \(CoreDataStack.identifier) \(DebuggingIdentifiers.succeeded) saved determination"
-                            )
-                        } catch {
-                            debugPrint(
-                                "OpenAPS: \(CoreDataStack.identifier) \(DebuggingIdentifiers.failed) error while saving determination"
-                            )
+
+                        if self.context.hasChanges {
+                            do {
+                                try self.context.save()
+                                debugPrint(
+                                    "OpenAPS: \(CoreDataStack.identifier) \(DebuggingIdentifiers.succeeded) saved determination"
+                                )
+                            } catch {
+                                debugPrint(
+                                    "OpenAPS: \(CoreDataStack.identifier) \(DebuggingIdentifiers.failed) error while saving determination"
+                                )
+                            }
                         }
                     }
 
@@ -159,23 +162,16 @@ final class OpenAPS {
 
                             saveToTDD.timestamp = determination.timestamp ?? Date()
                             saveToTDD.tdd = (determination.tdd ?? 0) as NSDecimalNumber?
-                            try? self.context.save()
+                            if self.context.hasChanges {
+                                try? self.context.save()
+                            }
 
                             let saveTarget = Target(context: self.context)
                             saveTarget.current = (determination.current_target ?? 100) as NSDecimalNumber?
-                            try? self.context.save()
+                            if self.context.hasChanges {
+                                try? self.context.save()
+                            }
                         }
-
-//                        self.coredataContext.perform {
-//                            let saveToInsulin = InsulinDistribution(context: self.coredataContext)
-//
-//                            saveToInsulin.bolus = (determination.insulin?.bolus ?? 0) as NSDecimalNumber?
-//                            saveToInsulin.scheduledBasal = (determination.insulin?.scheduled_basal ?? 0) as NSDecimalNumber?
-//                            saveToInsulin.tempBasal = (determination.insulin?.temp_basal ?? 0) as NSDecimalNumber?
-//                            saveToInsulin.date = Date()
-//
-//                            try? self.coredataContext.save()
-//                        }
                     }
 
                     promise(.success(determination))
@@ -275,7 +271,9 @@ final class OpenAPS {
                     saveToCoreData.duration = 0
                     saveToCoreData.indefinite = false
                     saveToCoreData.percentage = 100
-                    try? self.context.save()
+                    if self.context.hasChanges {
+                        try? self.context.save()
+                    }
                 }
             }
 
@@ -744,10 +742,12 @@ final class OpenAPS {
             forecastValue.forecast = forecast
         }
 
-        do {
-            try context.save()
-        } catch {
-            print("Failed to save forecast: \(error)")
+        if self.context.hasChanges {
+            do {
+                try context.save()
+            } catch {
+                print("Failed to save forecast: \(error)")
+            }
         }
     }
 }

+ 22 - 138
FreeAPS/Sources/APS/Storage/CarbsStorage.swift

@@ -153,15 +153,17 @@ final class BaseCarbsStorage: CarbsStorage, Injectable {
             newItem.carbs = Double(truncating: NSDecimalNumber(decimal: entry.carbs))
             newItem.id = UUID()
             newItem.isFPU = false
-            do {
-                try self.coredataContext.save()
-                debugPrint(
-                    "Carbs Storage: \(CoreDataStack.identifier) \(DebuggingIdentifiers.succeeded) saved carbs to core data"
-                )
-            } catch {
-                debugPrint(
-                    "Carbs Storage: \(CoreDataStack.identifier) \(DebuggingIdentifiers.failed) error while saving carbs to core data"
-                )
+            if self.coredataContext.hasChanges {
+                do {
+                    try self.coredataContext.save()
+                    debugPrint(
+                        "Carbs Storage: \(CoreDataStack.identifier) \(DebuggingIdentifiers.succeeded) saved carbs to core data"
+                    )
+                } catch {
+                    debugPrint(
+                        "Carbs Storage: \(CoreDataStack.identifier) \(DebuggingIdentifiers.failed) error while saving carbs to core data"
+                    )
+                }
             }
         }
     }
@@ -177,13 +179,17 @@ final class BaseCarbsStorage: CarbsStorage, Injectable {
             newItem.carbs = Double(truncating: NSDecimalNumber(decimal: entry.carbs))
             newItem.id = UUID()
             newItem.isFPU = true
-            do {
-                try self.coredataContext.save()
-                debugPrint("Carbs Storage: \(CoreDataStack.identifier) \(DebuggingIdentifiers.succeeded) saved fpus to core data")
-            } catch {
-                debugPrint(
-                    "Carbs Storage: \(CoreDataStack.identifier) \(DebuggingIdentifiers.succeeded) error while saving fpus to core data"
-                )
+            if self.coredataContext.hasChanges {
+                do {
+                    try self.coredataContext.save()
+                    debugPrint(
+                        "Carbs Storage: \(CoreDataStack.identifier) \(DebuggingIdentifiers.succeeded) saved fpus to core data"
+                    )
+                } catch {
+                    debugPrint(
+                        "Carbs Storage: \(CoreDataStack.identifier) \(DebuggingIdentifiers.succeeded) error while saving fpus to core data"
+                    )
+                }
             }
         }
     }
@@ -194,128 +200,6 @@ final class BaseCarbsStorage: CarbsStorage, Injectable {
         }
     }
 
-//    func storeCarbs(_ entries: [CarbsEntry]) {
-//        processQueue.sync {
-//            let file = OpenAPS.Monitor.carbHistory
-//            var uniqEvents: [CarbsEntry] = []
-//
-//            let fat = entries.last?.fat ?? 0
-//            let protein = entries.last?.protein ?? 0
-//
-//            if fat > 0 || protein > 0 {
-//                // -------------------------- FPU--------------------------------------
-//                let interval = settings.settings.minuteInterval // Interval betwwen carbs
-//                let timeCap = settings.settings.timeCap // Max Duration
-//                let adjustment = settings.settings.individualAdjustmentFactor
-//                let delay = settings.settings.delay // Tme before first future carb entry
-//                let kcal = protein * 4 + fat * 9
-//                let carbEquivalents = (kcal / 10) * adjustment
-//                let fpus = carbEquivalents / 10
-//                // Duration in hours used for extended boluses with Warsaw Method. Here used for total duration of the computed carbquivalents instead, excluding the configurable delay.
-//                var computedDuration = 0
-//                switch fpus {
-//                case ..<2:
-//                    computedDuration = 3
-//                case 2 ..< 3:
-//                    computedDuration = 4
-//                case 3 ..< 4:
-//                    computedDuration = 5
-//                default:
-//                    computedDuration = timeCap
-//                }
-//                // Size of each created carb equivalent if 60 minutes interval
-//                var equivalent: Decimal = carbEquivalents / Decimal(computedDuration)
-//                // Adjust for interval setting other than 60 minutes
-//                equivalent /= Decimal(60 / interval)
-//                // Round to 1 fraction digit
-//                // equivalent = Decimal(round(Double(equivalent * 10) / 10))
-//                let roundedEquivalent: Double = round(Double(equivalent * 10)) / 10
-//                equivalent = Decimal(roundedEquivalent)
-//                // Number of equivalents
-//                var numberOfEquivalents = carbEquivalents / equivalent
-//                // Only use delay in first loop
-//                var firstIndex = true
-//                // New date for each carb equivalent
-//                var useDate = entries.last?.actualDate ?? Date()
-//                // Group and Identify all FPUs together
-//                let fpuID = entries.last?.fpuID ?? ""
-//                // Create an array of all future carb equivalents.
-//                var futureCarbArray = [CarbsEntry]()
-//                while carbEquivalents > 0, numberOfEquivalents > 0 {
-//                    if firstIndex {
-//                        useDate = useDate.addingTimeInterval(delay.minutes.timeInterval)
-//                        firstIndex = false
-//                    } else { useDate = useDate.addingTimeInterval(interval.minutes.timeInterval) }
-//
-//                    let eachCarbEntry = CarbsEntry(
-//                        id: UUID().uuidString, createdAt: entries.last?.createdAt ?? Date(), actualDate: useDate,
-//                        carbs: equivalent, fat: 0, protein: 0, note: nil,
-//                        enteredBy: CarbsEntry.manual, isFPU: true,
-//                        fpuID: fpuID
-//                    )
-//                    futureCarbArray.append(eachCarbEntry)
-//                    numberOfEquivalents -= 1
-//                }
-//                // Save the array
-//                if carbEquivalents > 0 {
-//                    self.storage.transaction { storage in
-//                        storage.append(futureCarbArray, to: file, uniqBy: \.id)
-//                        uniqEvents = storage.retrieve(file, as: [CarbsEntry].self)?
-//                            .filter { $0.createdAt.addingTimeInterval(1.days.timeInterval) > Date() }
-//                            .sorted { $0.createdAt > $1.createdAt } ?? []
-//                        storage.save(Array(uniqEvents), as: file)
-//                    }
-//                }
-//            } // ------------------------- END OF TPU ----------------------------------------
-//            // Store the actual (normal) carbs
-//            if let entry = entries.last, entry.carbs > 0 {
-//                // uniqEvents = []
-//                let onlyCarbs = CarbsEntry(
-//                    id: entry.id ?? "",
-//                    createdAt: entry.createdAt,
-//                    actualDate: entry.actualDate ?? entry.createdAt,
-//                    carbs: entry.carbs,
-//                    fat: nil,
-//                    protein: nil,
-//                    note: entry.note ?? "",
-//                    enteredBy: entry.enteredBy ?? "",
-//                    isFPU: false,
-//                    fpuID: ""
-//                )
-//
-//                self.storage.transaction { storage in
-//                    storage.append(onlyCarbs, to: file, uniqBy: \.id)
-//                    uniqEvents = storage.retrieve(file, as: [CarbsEntry].self)?
-//                        .filter { $0.createdAt.addingTimeInterval(1.days.timeInterval) > Date() }
-//                        .sorted { $0.createdAt > $1.createdAt } ?? []
-//                    storage.save(Array(uniqEvents), as: file)
-//                }
-//            }
-
-    // MARK: Save to CoreData
-
-//            var cbs: Decimal = 0
-//            var carbDate = Date()
-//            if entries.isNotEmpty {
-//                cbs = entries[0].carbs
-//                carbDate = entries[0].actualDate ?? entries[0].createdAt
-//            }
-//            if cbs != 0 {
-//                self.coredataContext.perform {
-//                    let carbDataForStats = Carbohydrates(context: self.coredataContext)
-//
-//                    carbDataForStats.date = carbDate
-//                    carbDataForStats.carbs = cbs as NSDecimalNumber
-//
-//                    try? self.coredataContext.save()
-//                }
-//            }
-//            broadcaster.notify(CarbsObserver.self, on: processQueue) {
-//                $0.carbsDidUpdate(uniqEvents)
-//            }
-//        }
-//    }
-
     func syncDate() -> Date {
         Date().addingTimeInterval(-1.days.timeInterval)
     }

+ 11 - 9
FreeAPS/Sources/APS/Storage/GlucoseStorage.swift

@@ -84,15 +84,17 @@ final class BaseGlucoseStorage: GlucoseStorage, Injectable {
                         newItem.date = Date()
                         newItem.direction = direction
 
-                        do {
-                            try self.coredataContext.save()
-                            debugPrint(
-                                "Glucose Storage: \(CoreDataStack.identifier) \(DebuggingIdentifiers.succeeded) saved glucose to core data"
-                            )
-                        } catch {
-                            debugPrint(
-                                "Glucose Storage: \(CoreDataStack.identifier) \(DebuggingIdentifiers.failed) failed to save glucose to core data"
-                            )
+                        if self.coredataContext.hasChanges {
+                            do {
+                                try self.coredataContext.save()
+                                debugPrint(
+                                    "Glucose Storage: \(CoreDataStack.identifier) \(DebuggingIdentifiers.succeeded) saved glucose to core data"
+                                )
+                            } catch {
+                                debugPrint(
+                                    "Glucose Storage: \(CoreDataStack.identifier) \(DebuggingIdentifiers.failed) failed to save glucose to core data"
+                                )
+                            }
                         }
                     }
                 }

+ 11 - 9
FreeAPS/Sources/APS/Storage/PumpHistoryStorage.swift

@@ -48,15 +48,17 @@ final class BasePumpHistoryStorage: PumpHistoryStorage, Injectable {
                         new.id = UUID()
                         new.isSMB = true
 
-                        do {
-                            try self.context.save()
-                            debugPrint(
-                                "Pump History storage: \(#function) \(CoreDataStack.identifier) \(DebuggingIdentifiers.succeeded) saved smbs to core data"
-                            )
-                        } catch {
-                            debugPrint(
-                                "Pump History storage: \(#function) \(CoreDataStack.identifier) \(DebuggingIdentifiers.failed) failed to save smbs to core data"
-                            )
+                        if self.context.hasChanges {
+                            do {
+                                try self.context.save()
+                                debugPrint(
+                                    "Pump History storage: \(#function) \(CoreDataStack.identifier) \(DebuggingIdentifiers.succeeded) saved smbs to core data"
+                                )
+                            } catch {
+                                debugPrint(
+                                    "Pump History storage: \(#function) \(CoreDataStack.identifier) \(DebuggingIdentifiers.failed) failed to save smbs to core data"
+                                )
+                            }
                         }
                     }
 

+ 1 - 1
FreeAPS/Sources/Application/FreeAPSApp.swift

@@ -62,7 +62,7 @@ import Swinject
     var body: some Scene {
         WindowGroup {
             Main.RootView(resolver: resolver)
-                .environment(\.managedObjectContext, dataController.persistentContainer.viewContext)
+                .environment(\.managedObjectContext, dataController.viewContext)
                 .environmentObject(Icons())
                 .onOpenURL(perform: handleURL)
         }

+ 22 - 7
FreeAPS/Sources/Modules/AddTempTarget/AddTempTargetStateModel.swift

@@ -45,7 +45,10 @@ extension AddTempTarget {
                     saveToCoreData.date = Date()
                     saveToCoreData.duration = duration as NSDecimalNumber
                     saveToCoreData.startDate = Date()
-                    try? self.coredataContext.save()
+
+                    if self.coredataContext.hasChanges {
+                        try? self.coredataContext.save()
+                    }
                 }
                 saveSettings = true
             } else {
@@ -53,7 +56,9 @@ extension AddTempTarget {
                     let saveToCoreData = TempTargets(context: coredataContext)
                     saveToCoreData.active = false
                     saveToCoreData.date = Date()
-                    try? coredataContext.save()
+                    if self.coredataContext.hasChanges {
+                        try? coredataContext.save()
+                    }
                 }
             }
             var highTarget = lowTarget
@@ -84,12 +89,16 @@ extension AddTempTarget {
                 let saveToCoreData = TempTargets(context: self.coredataContext)
                 saveToCoreData.active = false
                 saveToCoreData.date = Date()
-                try? self.coredataContext.save()
+                if self.coredataContext.hasChanges {
+                    try? self.coredataContext.save()
+                }
 
                 let setHBT = TempTargetsSlider(context: self.coredataContext)
                 setHBT.enabled = false
                 setHBT.date = Date()
-                try? self.coredataContext.save()
+                if self.coredataContext.hasChanges {
+                    try? self.coredataContext.save()
+                }
             }
         }
 
@@ -133,7 +142,9 @@ extension AddTempTarget {
                     saveToCoreData.hbt = hbt
                     saveToCoreData.date = Date()
                     saveToCoreData.duration = duration as NSDecimalNumber
-                    try? self.coredataContext.save()
+                    if self.coredataContext.hasChanges {
+                        try? self.coredataContext.save()
+                    }
                 }
             }
         }
@@ -162,12 +173,16 @@ extension AddTempTarget {
                         saveToCoreData.startDate = Date()
                         saveToCoreData.duration = whichID?.duration ?? 0
 
-                        try? self.coredataContext.save()
+                        if self.coredataContext.hasChanges {
+                            try? self.coredataContext.save()
+                        }
                     } else {
                         let saveToCoreData = TempTargets(context: self.coredataContext)
                         saveToCoreData.active = false
                         saveToCoreData.date = Date()
-                        try? self.coredataContext.save()
+                        if self.coredataContext.hasChanges {
+                            try? self.coredataContext.save()
+                        }
                     }
                 }
             }

+ 26 - 19
FreeAPS/Sources/Modules/Bolus/BolusStateModel.swift

@@ -363,15 +363,17 @@ extension Bolus {
             newItem.external = false
             newItem.isSMB = false
             context.perform {
-                do {
-                    try self.context.save()
-                    debugPrint(
-                        "Bolus State: \(CoreDataStack.identifier) \(DebuggingIdentifiers.succeeded) saved pump insulin to core data"
-                    )
-                } catch {
-                    debugPrint(
-                        "Bolus State: \(CoreDataStack.identifier) \(DebuggingIdentifiers.failed) failed to save pump insulin to core data"
-                    )
+                if self.context.hasChanges {
+                    do {
+                        try self.context.save()
+                        debugPrint(
+                            "Bolus State: \(CoreDataStack.identifier) \(DebuggingIdentifiers.succeeded) saved pump insulin to core data"
+                        )
+                    } catch {
+                        debugPrint(
+                            "Bolus State: \(CoreDataStack.identifier) \(DebuggingIdentifiers.failed) failed to save pump insulin to core data"
+                        )
+                    }
                 }
             }
         }
@@ -431,15 +433,17 @@ extension Bolus {
                 newItem.date = Date()
                 newItem.external = true
                 newItem.isSMB = false
-                do {
-                    try self.context.save()
-                    debugPrint(
-                        "Bolus State: \(CoreDataStack.identifier) \(DebuggingIdentifiers.succeeded) saved carbs to core data"
-                    )
-                } catch {
-                    debugPrint(
-                        "Bolus State: \(CoreDataStack.identifier) \(DebuggingIdentifiers.failed) failed to save carbs to core data"
-                    )
+                if self.context.hasChanges {
+                    do {
+                        try self.context.save()
+                        debugPrint(
+                            "Bolus State: \(CoreDataStack.identifier) \(DebuggingIdentifiers.succeeded) saved carbs to core data"
+                        )
+                    } catch {
+                        debugPrint(
+                            "Bolus State: \(CoreDataStack.identifier) \(DebuggingIdentifiers.failed) failed to save carbs to core data"
+                        )
+                    }
                 }
             }
 
@@ -482,7 +486,10 @@ extension Bolus {
         func deletePreset() {
             if selection != nil {
                 try? context.delete(selection!)
-                try? context.save()
+
+                if context.hasChanges {
+                    try? context.save()
+                }
                 carbs = 0
                 fat = 0
                 protein = 0

+ 3 - 1
FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift

@@ -106,7 +106,9 @@ extension Bolus {
                             preset.fat = state.fat as NSDecimalNumber
                             preset.protein = state.protein as NSDecimalNumber
                             preset.carbs = state.carbs as NSDecimalNumber
-                            try? moc.save()
+                            if self.moc.hasChanges {
+                                try? moc.save()
+                            }
                             state.addNewPresetToWaitersNotepad(dish)
                             saved = false
                             isPromptPresented = false

+ 11 - 9
FreeAPS/Sources/Modules/DataTable/DataTableStateModel.swift

@@ -257,15 +257,17 @@ extension DataTable {
             newItem.glucose = Int16(glucoseAsInt)
             newItem.isManual = true
 
-            do {
-                try coredataContext.save()
-                debugPrint(
-                    "Data table state model: \(#function) \(CoreDataStack.identifier) \(DebuggingIdentifiers.succeeded) added manual glucose to core data"
-                )
-            } catch {
-                debugPrint(
-                    "Data table state model: \(#function) \(CoreDataStack.identifier) \(DebuggingIdentifiers.failed) failed to add manual glucose to core data"
-                )
+            if coredataContext.hasChanges {
+                do {
+                    try coredataContext.save()
+                    debugPrint(
+                        "Data table state model: \(#function) \(CoreDataStack.identifier) \(DebuggingIdentifiers.succeeded) added manual glucose to core data"
+                    )
+                } catch {
+                    debugPrint(
+                        "Data table state model: \(#function) \(CoreDataStack.identifier) \(DebuggingIdentifiers.failed) failed to add manual glucose to core data"
+                    )
+                }
             }
         }
     }

+ 3 - 1
FreeAPS/Sources/Modules/Home/HomeStateModel.swift

@@ -207,7 +207,9 @@ extension Home {
                 let profiles = Override(context: self.context)
                 profiles.enabled = false
                 profiles.date = Date()
-                try? self.context.save()
+                if self.context.hasChanges {
+                    try? self.context.save()
+                }
             }
         }
 

+ 30 - 10
FreeAPS/Sources/Modules/OverrideProfilesConfig/OverrideProfilesStateModel.swift

@@ -95,7 +95,9 @@ extension OverrideProfilesConfig {
                     saveOverride.smbMinutes = smbMinutes as NSDecimalNumber
                     saveOverride.uamMinutes = uamMinutes as NSDecimalNumber
                 }
-                try? self.coredataContext.save()
+                if self.coredataContext.hasChanges {
+                    try? self.coredataContext.save()
+                }
             }
         }
 
@@ -136,7 +138,9 @@ extension OverrideProfilesConfig {
                     saveOverride.smbMinutes = smbMinutes as NSDecimalNumber
                     saveOverride.uamMinutes = uamMinutes as NSDecimalNumber
                 }
-                try? self.coredataContext.save()
+                if self.coredataContext.hasChanges {
+                    try? self.coredataContext.save()
+                }
             }
         }
 
@@ -176,7 +180,9 @@ extension OverrideProfilesConfig {
                     saveOverride.smbMinutes = (profile.smbMinutes ?? 0) as NSDecimalNumber
                     saveOverride.uamMinutes = (profile.uamMinutes ?? 0) as NSDecimalNumber
                 }
-                try? self.coredataContext.save()
+                if self.coredataContext.hasChanges {
+                    try? self.coredataContext.save()
+                }
             }
         }
 
@@ -262,7 +268,9 @@ extension OverrideProfilesConfig {
                 let profiles = Override(context: self.coredataContext)
                 profiles.enabled = false
                 profiles.date = Date()
-                try? self.coredataContext.save()
+                if self.coredataContext.hasChanges {
+                    try? self.coredataContext.save()
+                }
             }
             smbMinutes = defaultSmbMinutes
             uamMinutes = defaultUamMinutes
@@ -294,7 +302,9 @@ extension OverrideProfilesConfig {
                     let saveToCoreData = TempTargets(context: coredataContext)
                     saveToCoreData.active = false
                     saveToCoreData.date = Date()
-                    try? coredataContext.save()
+                    if self.coredataContext.hasChanges {
+                        try? coredataContext.save()
+                    }
                 }
             }
             var highTarget = lowTarget
@@ -325,12 +335,16 @@ extension OverrideProfilesConfig {
                 let saveToCoreData = TempTargets(context: self.coredataContext)
                 saveToCoreData.active = false
                 saveToCoreData.date = Date()
-                try? self.coredataContext.save()
+                if self.coredataContext.hasChanges {
+                    try? self.coredataContext.save()
+                }
 
                 let setHBT = TempTargetsSlider(context: self.coredataContext)
                 setHBT.enabled = false
                 setHBT.date = Date()
-                try? self.coredataContext.save()
+                if self.coredataContext.hasChanges {
+                    try? self.coredataContext.save()
+                }
             }
         }
 
@@ -374,7 +388,9 @@ extension OverrideProfilesConfig {
                     saveToCoreData.hbt = hbt
                     saveToCoreData.date = Date()
                     saveToCoreData.duration = durationTT as NSDecimalNumber
-                    try? self.coredataContext.save()
+                    if self.coredataContext.hasChanges {
+                        try? self.coredataContext.save()
+                    }
                 }
             }
         }
@@ -403,12 +419,16 @@ extension OverrideProfilesConfig {
                         saveToCoreData.startDate = Date()
                         saveToCoreData.duration = whichID?.duration ?? 0
 
-                        try? self.coredataContext.save()
+                        if self.coredataContext.hasChanges {
+                            try? self.coredataContext.save()
+                        }
                     } else {
                         let saveToCoreData = TempTargets(context: self.coredataContext)
                         saveToCoreData.active = false
                         saveToCoreData.date = Date()
-                        try? self.coredataContext.save()
+                        if self.coredataContext.hasChanges {
+                            try? self.coredataContext.save()
+                        }
                     }
                 }
             }

+ 6 - 4
FreeAPS/Sources/Modules/OverrideProfilesConfig/View/OverrideProfilesRootView.swift

@@ -650,10 +650,12 @@ extension OverrideProfilesConfig {
                 let language = fetchedProfiles[index]
                 moc.delete(language)
             }
-            do {
-                try moc.save()
-            } catch {
-                // To do: add error
+            if moc.hasChanges {
+                do {
+                    try moc.save()
+                } catch {
+                    // To do: add error
+                }
             }
         }
     }

+ 15 - 6
FreeAPS/Sources/Shortcuts/TempPresets/TempPresetsIntentRequest.swift

@@ -42,7 +42,9 @@ import Foundation
             let requestTempTargets = TempTargetsSlider.fetchRequest() as NSFetchRequest<TempTargetsSlider>
             let sortTT = NSSortDescriptor(key: "date", ascending: false)
             requestTempTargets.sortDescriptors = [sortTT]
-            try? tempTargetsArray = coredataContext.fetch(requestTempTargets)
+            if coredataContext.hasChanges {
+                try? tempTargetsArray = coredataContext.fetch(requestTempTargets)
+            }
 
             let whichID = tempTargetsArray.first(where: { $0.id == tempTarget.id })
 
@@ -54,12 +56,16 @@ import Foundation
                 saveToCoreData.startDate = Date()
                 saveToCoreData.duration = whichID?.duration ?? 0
 
-                try? self.coredataContext.save()
+                if coredataContext.hasChanges {
+                    try? self.coredataContext.save()
+                }
             } else {
                 let saveToCoreData = TempTargets(context: self.coredataContext)
                 saveToCoreData.active = false
                 saveToCoreData.date = Date()
-                try? self.coredataContext.save()
+                if coredataContext.hasChanges {
+                    try? self.coredataContext.save()
+                }
             }
         }
 
@@ -72,13 +78,16 @@ import Foundation
             let saveToCoreData = TempTargets(context: self.coredataContext)
             saveToCoreData.active = false
             saveToCoreData.date = Date()
-            try self.coredataContext.save()
+            if coredataContext.hasChanges {
+                try self.coredataContext.save()
+            }
 
             let setHBT = TempTargetsSlider(context: self.coredataContext)
             setHBT.enabled = false
             setHBT.date = Date()
-
-            try self.coredataContext.save()
+            if coredataContext.hasChanges {
+                try self.coredataContext.save()
+            }
         }
     }
 }