1

I'm working on an app that needs to process cached location data in the background periodically. While the task usually completes in less than 30 seconds, it could potentially be battery- and network-intensive, as it reverse-geocodes multiple cached locations. And since the task can be considered "database maintenance", I would like to implement it as a background processing task (BGProcessingTask).

I am trying to use SwiftUI's backgroundTask(_:) scene modifier to handle the task. I have watched the "Efficiency Awaits" WWDC video (https://developer.apple.com/wwdc22/10142) and read the documentation, and I have not found any information about how to handle BGProcessingTasks. BackgroundTask provides appRefresh and urlSession tasks, but not background processing tasks.

I have tried registering a BGProcessingTaskRequest, and then handling it with .appRefresh. A simplified version of my code looks like this:

struct MyApp: App {
    @Environment(\.scenePhase) private var scenePhase

    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .onChange(of: scenePhase) { _, newValue in
            if case .background = newValue {
                scheduleBackgroundTasks()
            }
        }
        .backgroundTask(.appRefresh("com.MyCompany.MyApp-ProcessLocations")) {
            scheduleBackgroundTasks()
            do {
                try await AppDataStore.processLocations()
            } catch {
                print(error)
            }
        }
    }
}

func scheduleBackgroundTasks() {
    let taskDate = nextTaskDate()
    let bgTaskRequest = BGProcessingTaskRequest(
        identifier: "com.MyCompany.MyApp-ProcessLocations"
    )
    bgTaskRequest.earliestBeginDate = taskDate
    bgTaskRequest.requiresExternalPower = true
    bgTaskRequest.requiresNetworkConnectivity = true
    try? BGTaskScheduler.shared.submit(bgTaskRequest)
}

The task successfully runs when triggering it with the debugging method used in the WWDC videos, but since I can't find any published info on the subject, I don't know if it's safe to do this in production.

What are the implications of handling the processing task with .appRefresh? For example will the system allow my app to run for the amount of time allocated to processing tasks, or will it be terminated after 30 seconds like an app refresh task? Will the backgroundTask modifier correctly tell the system when the task completes?

Finally, if the backgroundTask modifier can't be used, how should background processing tasks be handled in a SwiftUI app?

2
  • I think the differences between an app refresh task and a processing task, as far as .backgroundTask is concerned, are insignificant so Apple decided to use one BckgroundTask type for both. In the case where an app has both kinds of tasks it can identify which it is dealing with by examining the task identifier. If it works in testing then it will work Commented Apr 13, 2024 at 21:05
  • That's what I've been thinking, but was hoping someone knew something more definitive. I'll continue to use it for now, since as you pointed out, it seems to be working. Commented Apr 14, 2024 at 18:26

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.