I kept getting the error
No task request with identifier <decode: missing data> has been scheduled
in my debugger output so I decided to try running the example code provided by Apple here and got the same error. I’ve tried multiple computers and Xcode versions, multiple example projects from different sources and nothing has worked.
My AppDelegate.swift file:
import UIKit
import Firebase
import BackgroundTasks
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
BGTaskScheduler.shared.register(forTaskWithIdentifier: “redacted.identifier”, using: nil) { task in
self.handleAppRefresh(task: task as! BGAppRefreshTask)
}
return true
}
func applicationDidEnterBackground(_ application: UIApplication) {
BGTaskScheduler.shared.cancelAllTaskRequests()
scheduleAppRefresh()
}
func scheduleAppRefresh() {
let request = BGAppRefreshTaskRequest(identifier: "redacted.identifier")
request.earliestBeginDate = Date(timeIntervalSinceNow: 60)
do {
try BGTaskScheduler.shared.submit(request)
} catch {
print("Could not schedule app refresh: (error)")
}
}
func handleAppRefresh(task: BGAppRefreshTask) {
scheduleAppRefresh()
let db = Firestore.firestore()
db.collection("devices").document(UIDevice.current.identifierForVendor!.uuidString).setData([
"batteryLevel": UIDevice.current.batteryLevel*100
]) { err in
if let err = err {
print("Error writing document: (err)")
} else {
print("success")
task.setTaskCompleted(success: true)
}
}
task.expirationHandler = {
task.setTaskCompleted(success: false)
}
}
I am testing background fetch by running
e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@"redacted.identifier"]
in the Xcode console, after which the error above occurs.
Console output:
Simulating launch for task with identifier redacted.identifier
No task request with identifier <decode: missing data> has been scheduled
4
Answers
A couple of potential issues:
This happens when testing on the simulator. Use a physical device.
Make sure your
Info.plist
has a “Permitted background task scheduler identifiers” (i.e.BGTaskSchedulerPermittedIdentifiers
) entry with the identifier for your background task.Make sure you set your breakpoint immediately after the
BGTaskScheduler.shared.submit(...)
line and that you perform the_simulateLaunchForTaskWithIdentifier
aftersubmit
was called. I.e., make sure you are even getting to thesubmit
call. (See next point.)Notably, the Apple example (and your example) are scheduling it in
applicationDidEnterBackground(_:)
. But if you are using aUIWindowSceneDelegate
(i.e. in yourSceneDelegate
), then the app delegate’sapplicationDidEnterBackground(_:)
is not called, but rather the scene delegate’ssceneDidEnterBackground(_:)
is. I put the scheduling of theBGAppRefreshTaskRequest
in the scene delegate’ssceneDidEnterBackground(_:)
.I got the same issue when I tested on a Device.
Go to Device Settings > General > Background App Refresh and turn on Background App Refresh. This issue has gone after it.
There is one another case that isn’t mentioned in other answers, if you’re trying to submit different or more than 1 refresh tasks you might be hitting the error case below. Issue is, currently the mentioned error isn’t thrown in Xcode 13.1, so it looks like submitting request works, but basically it doesn’t.
Apple doc: There can be a total of 1 refresh task and 10 processing tasks scheduled at any time. Trying to schedule more tasks returns BGTaskScheduler.Error.Code.tooManyPendingTaskRequests.
It looks like
applicationDidEnterBackground
is never get called, check it out (add breakpoint).because of a scene-based configured lifecycle
If it’s true, move your logic into SceneDelegate class