13

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):

enter image description here

Then, I prepared the Info.plist according to the docs (Identifier is fake just for StackOverflow question):

enter image description here

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.

TylerH
  • 20,799
  • 66
  • 75
  • 101
Bar Malka
  • 550
  • 1
  • 4
  • 13
  • 4
    The task will be executed only when the system decides to do so. It can execute when the device is charging, etc. As you said the exact success can’t be guaranteed. Watch WWDC 2019 session # 707 for more info. – badhanganesh Dec 23 '19 at 12:07
  • @badhanganesh, Thank you for the quick response. Do you have a solution to run a function after X seconds (not minutes..) after going into background? iOS 13. – Bar Malka Dec 23 '19 at 12:09
  • Use an application background task. That gives you 30 seconds of extra time. – matt Dec 24 '19 at 09:32
  • 1
    @matt I used it, it doesn't seem to work exactly every time I used it, can you post an answer with implementation for using a 5 seconds timer? I tried as Apple docs say. – Bar Malka Dec 25 '19 at 10:07

1 Answers1

12

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.

Bar Malka
  • 550
  • 1
  • 4
  • 13
  • 2
    @mykolaj, I believe there is probably some way to do it, that's probably why people downvoted. I stopped working on it since product definition changed and I had no time to put effort on solving it. – Bar Malka May 10 '20 at 17:33
  • 2
    No. I think people are downvoting because they knows this thing. And you are 100% correct that system will decide. there is no other way to do it in BGTaskSchedular – Mubin Mall May 12 '20 at 05:46