Jul 27 - Update code for scheduled tasks 4
This commit is contained in:
@@ -128,7 +128,11 @@ struct JanitorialQCApp: App {
|
||||
}
|
||||
|
||||
private func registerBackgroundTasks() {
|
||||
BGTaskScheduler.shared.register(
|
||||
// register() returns false when the identifier is not declared in
|
||||
// BGTaskSchedulerPermittedIdentifiers or the `processing` background
|
||||
// mode is missing. Both are easy to lose in a project settings change
|
||||
// and the failure is otherwise completely silent, so it is logged.
|
||||
let registered = BGTaskScheduler.shared.register(
|
||||
forTaskWithIdentifier: "com.jqc.sync",
|
||||
using: nil
|
||||
) { task in
|
||||
@@ -138,16 +142,44 @@ struct JanitorialQCApp: App {
|
||||
}
|
||||
handleBackgroundSync(task: processingTask)
|
||||
}
|
||||
if !registered {
|
||||
print("[JQC] BGTaskScheduler.register FAILED for com.jqc.sync — "
|
||||
+ "check UIBackgroundModes contains 'processing' and "
|
||||
+ "BGTaskSchedulerPermittedIdentifiers contains com.jqc.sync")
|
||||
}
|
||||
}
|
||||
|
||||
private func handleBackgroundSync(task: BGProcessingTask) {
|
||||
// Re-arm first: if anything below throws or the task is killed, a
|
||||
// request is already queued for the next opportunity.
|
||||
scheduleBackgroundSync()
|
||||
let syncTask = Task {
|
||||
|
||||
let syncTask = Task { @MainActor in
|
||||
// A BGTaskScheduler launch does not render ContentView, so the
|
||||
// `.task { restoreSession() }` there never runs and
|
||||
// AuthManager.isAuthenticated is still false. triggerSync() guards
|
||||
// on it and would return having done nothing at all.
|
||||
if !AuthManager.shared.isAuthenticated {
|
||||
await AuthManager.shared.restoreSession()
|
||||
}
|
||||
|
||||
// The SwiftData container is created by the `.modelContainer`
|
||||
// scene modifier, so on a COLD background launch (process was
|
||||
// terminated, no scene connected) there is no context to drain.
|
||||
// The common case — app suspended but still resident — has one.
|
||||
guard SyncManager.shared.modelContext != nil else {
|
||||
print("[JQC] background sync skipped — no model context "
|
||||
+ "(cold launch, no scene)")
|
||||
return
|
||||
}
|
||||
|
||||
await SyncManager.shared.triggerSync()
|
||||
}
|
||||
|
||||
task.expirationHandler = {
|
||||
syncTask.cancel()
|
||||
}
|
||||
|
||||
Task {
|
||||
await syncTask.value
|
||||
task.setTaskCompleted(success: !syncTask.isCancelled)
|
||||
@@ -178,5 +210,12 @@ func scheduleBackgroundSync() {
|
||||
let request = BGProcessingTaskRequest(identifier: "com.jqc.sync")
|
||||
request.requiresNetworkConnectivity = true
|
||||
request.requiresExternalPower = false
|
||||
try? BGTaskScheduler.shared.submit(request)
|
||||
do {
|
||||
try BGTaskScheduler.shared.submit(request)
|
||||
} catch {
|
||||
// Was `try?`. Submitting without the `processing` background mode fails
|
||||
// with BGTaskSchedulerError.notPermitted, which is exactly how this
|
||||
// whole path stayed dead unnoticed. Never swallow it again.
|
||||
print("[JQC] BGTaskScheduler.submit failed: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user