THE PROBLEM: I want to run a simple function, 5 seconds after app goes into background.
I had to implement BGTaskScheduler, to support iOS 13. The old implementation for BackgroundTask works for me on older iOS versions.
I added background modes as requested (BLE accessories is ticked because we perform a small BLE operation in this function):
Then, I prepared the Info.plist according to the docs (Identifier is fake just for StackOverflow question):
Before didFinishLaunchingWithOptions is ended, I register my BackgroundTask:
if #available(iOS 13.0, *) {
BGTaskScheduler.shared.register(forTaskWithIdentifier: "com.example.MyID", using: .global()) { (task) in
print("My backgroundTask is executed NOW!")
task.expirationHandler = {
task.setTaskCompleted(success: true)
}
}
}
Now, when the app run the didEnterBackground method, I submit a BackgroundTaskRequest:
if #available(iOS 13.0, *) {
do {
let request = BGAppRefreshTaskRequest(identifier: "com.example.MyID")
request.earliestBeginDate = Calendar.current.date(byAdding: .second, value: 5, to: Date())
try BGTaskScheduler.shared.submit(request)
print("Submitted task request")
} catch {
print("Failed to submit BGTask")
}
}
The problem here is that it is VERY inconsistent. Apple guarantee that the task will not be executed before the given date, but does not guarantee that it will be executed on the exact time (I'm fine with a small delay). However, when I ran the app, it did not work 100% of the times, regardless if I provided the task request a delay (using earliestBeginDate) so it used to go first try 7 seconds (instead of 5), next time I submitted the task it took 26 seconds, third time never arrived the closure.
Am I implementing the BackgroundTask the wrong way? I've searched all over the internet some answer but did not encounter anyone having this problem.
As badhanganesh said, It seems like the task will be executed only when the system decides to do so. Apple said that during WWWDC 2019, session #707.