|
|
@@ -78,7 +78,7 @@ import UIKit
|
|
|
}
|
|
|
|
|
|
@MainActor func enactOverride(_ preset: OverridePreset) async -> Bool {
|
|
|
- // Start background task to ensure that the task can run in background mode
|
|
|
+ // Start background task
|
|
|
var backgroundTaskID: UIBackgroundTaskIdentifier = .invalid
|
|
|
backgroundTaskID = await UIApplication.shared.beginBackgroundTask(withName: "Override Upload") {
|
|
|
guard backgroundTaskID != .invalid else { return }
|
|
|
@@ -89,14 +89,21 @@ import UIKit
|
|
|
backgroundTaskID = .invalid
|
|
|
}
|
|
|
|
|
|
+ // Defer block to end background task when function exits
|
|
|
+ defer {
|
|
|
+ if backgroundTaskID != .invalid {
|
|
|
+ Task {
|
|
|
+ await UIApplication.shared.endBackgroundTask(backgroundTaskID)
|
|
|
+ }
|
|
|
+ backgroundTaskID = .invalid
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
do {
|
|
|
+ // Get NSManagedObjectID of Preset
|
|
|
guard let overrideID = await fetchOverrideID(preset),
|
|
|
let overrideObject = try viewContext.existingObject(with: overrideID) as? OverrideStored
|
|
|
- else {
|
|
|
- // Be sure to end background task if error occurs
|
|
|
- await UIApplication.shared.endBackgroundTask(backgroundTaskID)
|
|
|
- return false
|
|
|
- }
|
|
|
+ else { return false }
|
|
|
|
|
|
// Enable Override
|
|
|
overrideObject.enabled = true
|
|
|
@@ -117,18 +124,13 @@ import UIKit
|
|
|
await awaitNotification(.didUpdateOverrideConfiguration)
|
|
|
print("Notification received, continuing...")
|
|
|
|
|
|
- // End background task after everything is done
|
|
|
- await UIApplication.shared.endBackgroundTask(backgroundTaskID)
|
|
|
return true
|
|
|
}
|
|
|
} catch {
|
|
|
// Handle error and ensure background task is ended
|
|
|
debugPrint("Failed to enact Override: \(error.localizedDescription)")
|
|
|
- await UIApplication.shared.endBackgroundTask(backgroundTaskID)
|
|
|
}
|
|
|
|
|
|
- // Make sure background task ends in any case
|
|
|
- await UIApplication.shared.endBackgroundTask(backgroundTaskID)
|
|
|
return false
|
|
|
}
|
|
|
|
|
|
@@ -140,59 +142,77 @@ import UIKit
|
|
|
except overrideID: NSManagedObjectID? = nil,
|
|
|
createOverrideRunEntry _: Bool
|
|
|
) async {
|
|
|
- // Get ALL NSManagedObject IDs of ALL active Overrides to cancel every single Override
|
|
|
- let ids = await overrideStorage.loadLatestOverrideConfigurations(fetchLimit: 0) // 0 = no fetch limit
|
|
|
+ // Start background task
|
|
|
+ var backgroundTaskID: UIBackgroundTaskIdentifier = .invalid
|
|
|
+ backgroundTaskID = await UIApplication.shared.beginBackgroundTask(withName: "Override Cancel") {
|
|
|
+ guard backgroundTaskID != .invalid else { return }
|
|
|
+ Task {
|
|
|
+ // End background task when the time is about to expire
|
|
|
+ await UIApplication.shared.endBackgroundTask(backgroundTaskID)
|
|
|
+ }
|
|
|
+ backgroundTaskID = .invalid
|
|
|
+ }
|
|
|
|
|
|
- await viewContext.perform {
|
|
|
- do {
|
|
|
- // Fetch the existing OverrideStored objects from the context
|
|
|
- let results = try ids.compactMap { id in
|
|
|
- try self.viewContext.existingObject(with: id) as? OverrideStored
|
|
|
+ // Defer block to end background task when function exits
|
|
|
+ defer {
|
|
|
+ if backgroundTaskID != .invalid {
|
|
|
+ Task {
|
|
|
+ await UIApplication.shared.endBackgroundTask(backgroundTaskID)
|
|
|
}
|
|
|
+ backgroundTaskID = .invalid
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- // If there are no results, return early
|
|
|
- guard !results.isEmpty else { return }
|
|
|
-
|
|
|
- // Check if we also need to create a corresponding OverrideRunStored entry, i.e. when the User uses the Cancel Button in Override View
|
|
|
- // Auggie - commented out this if statment, we always need to do this for overrides
|
|
|
- // if createOverrideRunEntry {
|
|
|
- // Use the first override to create a new OverrideRunStored entry
|
|
|
- if let canceledOverride = results.first {
|
|
|
- let newOverrideRunStored = OverrideRunStored(context: self.viewContext)
|
|
|
- newOverrideRunStored.id = UUID()
|
|
|
- newOverrideRunStored.name = canceledOverride.name
|
|
|
- newOverrideRunStored.startDate = canceledOverride.date ?? .distantPast
|
|
|
- newOverrideRunStored.endDate = Date()
|
|
|
- newOverrideRunStored
|
|
|
- .target = NSDecimalNumber(
|
|
|
- decimal: self.overrideStorage
|
|
|
- .calculateTarget(override: canceledOverride)
|
|
|
- )
|
|
|
- newOverrideRunStored.override = canceledOverride
|
|
|
- newOverrideRunStored.isUploadedToNS = false
|
|
|
- }
|
|
|
- // }
|
|
|
-
|
|
|
- // Disable all override except the one with overrideID
|
|
|
- for overrideToCancel in results {
|
|
|
- if overrideToCancel.objectID != overrideID {
|
|
|
- overrideToCancel.enabled = false
|
|
|
- overrideToCancel.isUploadedToNS = false
|
|
|
- }
|
|
|
- }
|
|
|
+ // Get NSManagedObjectID of all active overrides
|
|
|
+ let ids = await overrideStorage.loadLatestOverrideConfigurations(fetchLimit: 0) // 0 = no fetch limit
|
|
|
|
|
|
- // Save the context if there are changes
|
|
|
- if self.viewContext.hasChanges {
|
|
|
- try self.viewContext.save()
|
|
|
+ do {
|
|
|
+ // Fetch existing OverrideStored objects
|
|
|
+ let results = try ids.compactMap { id in
|
|
|
+ try self.viewContext.existingObject(with: id) as? OverrideStored
|
|
|
+ }
|
|
|
|
|
|
- // Update State variables in OverrideView
|
|
|
- Foundation.NotificationCenter.default.post(name: .didUpdateOverrideConfiguration, object: nil)
|
|
|
- }
|
|
|
- } catch {
|
|
|
- debugPrint(
|
|
|
- "\(DebuggingIdentifiers.failed) \(#file) \(#function) Failed to disable active Overrides with error: \(error.localizedDescription)"
|
|
|
+ // Return early if no results (background task remains active until defer block executes)
|
|
|
+ guard !results.isEmpty else { return }
|
|
|
+
|
|
|
+ // Create OverrideRunStored entry if needed
|
|
|
+ if let canceledOverride = results.first {
|
|
|
+ let newOverrideRunStored = OverrideRunStored(context: viewContext)
|
|
|
+ newOverrideRunStored.id = UUID()
|
|
|
+ newOverrideRunStored.name = canceledOverride.name
|
|
|
+ newOverrideRunStored.startDate = canceledOverride.date ?? .distantPast
|
|
|
+ newOverrideRunStored.endDate = Date()
|
|
|
+ newOverrideRunStored.target = NSDecimalNumber(
|
|
|
+ decimal: overrideStorage.calculateTarget(override: canceledOverride)
|
|
|
)
|
|
|
+ newOverrideRunStored.override = canceledOverride
|
|
|
+ newOverrideRunStored.isUploadedToNS = false
|
|
|
+ }
|
|
|
+
|
|
|
+ // Disable all overrides except the one specified
|
|
|
+ for overrideToCancel in results {
|
|
|
+ if overrideToCancel.objectID != overrideID {
|
|
|
+ overrideToCancel.enabled = false
|
|
|
+ overrideToCancel.isUploadedToNS = false
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
+ if viewContext.hasChanges {
|
|
|
+ try viewContext.save()
|
|
|
+
|
|
|
+ // Update State variables in OverrideView
|
|
|
+ Foundation.NotificationCenter.default.post(name: .willUpdateOverrideConfiguration, object: nil)
|
|
|
+ }
|
|
|
+
|
|
|
+ // Await the notification
|
|
|
+ print("Waiting for notification...")
|
|
|
+ await awaitNotification(.didUpdateOverrideConfiguration)
|
|
|
+ print("Notification received, continuing...")
|
|
|
+
|
|
|
+ } catch {
|
|
|
+ debugPrint(
|
|
|
+ "\(DebuggingIdentifiers.failed) \(#file) \(#function) Failed to disable active Overrides with error: \(error.localizedDescription)"
|
|
|
+ )
|
|
|
}
|
|
|
}
|
|
|
}
|