4mahmoud
4mahmoud

Reputation: 853

BGTaskScheduler.shared.register Not Called

I'm using background refresh to schedule local notifications and update my widget. The problem is that the task registration method isn't called!

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        
    BGTaskScheduler.shared.register(forTaskWithIdentifier: "com.Mahmoud.AdaniLite.AppRefresh", using: nil) { task in
        print("Registered")
        self.handleAppRefresh(task: task as! BGAppRefreshTask)
    }
  return true
} 

I also have a break point inside the register method with a print statement but non of both worked!

I have done my research and so far i have tried the following already:

  1. I made sure 'Permitted background task scheduler identifiers' in the info.plist is filled with the correct task identifier. I have triple checked that this string gets used correctly in the code as well.
  2. Enabled 'Background fetch' capability.
  3. In the info.plist I added "App processes data in the background" to the "Required background modes"
  4. I'm running the app on a real device running iOS 15

Any help or guidance is deeply appreciated!

Upvotes: 6

Views: 5642

Answers (3)

scosman
scosman

Reputation: 2585

If you register and schedule properly, and want to test your task, you can do the following.

  1. Set a breakpoint
  2. While paused, run the lldb debugger command: e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@"YOUR_REFRESH_TASK_ID"]

Source: https://developer.apple.com/documentation/backgroundtasks/starting-and-terminating-tasks-during-development?language=objc

Upvotes: 0

Antomur
Antomur

Reputation: 81

I had exactly the same problem as you, and I've been trying to solve it for several hours!

And I've found a solution!

Here are the steps:

In the AppDelegate:

func application(_ application: UIApplication, didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
    // …
    SchedulingService.shared.registerBackgroundTasks()
    return true
}

My service:

class SchedulingService {
    static let shared = SchedulingService()
        
    func registerBackgroundTasks() {
        let isRegistered = BGTaskScheduler.shared.register(forTaskWithIdentifier: "com.YOUR.refresh", using: nil) { task in
            print("Background task is executing: \(task.identifier)")
            self.handleAppRefresh(task: task as! BGAppRefreshTask)
        }
        print("Is the background task registered? \(isRegistered)")
    }
    
    func scheduleAppRefresh() {
        let request = BGAppRefreshTaskRequest(identifier: "com.YOUR.refresh")
        
        request.earliestBeginDate = Date(timeIntervalSinceNow: 60 * 2)
        
        do {
            try BGTaskScheduler.shared.submit(request)
        } catch {
            print("Could not schedule app refresh: \(error)")
        }
    }
    
    private func handleAppRefresh(task: BGAppRefreshTask) {
        // <!-- Your background logic here -->
        // <!-- LocalNotificationService.sharedInstance.initScheduleNotifications() -->

        task.setTaskCompleted(success: true)
        
        scheduleAppRefresh()
    }
}

Now, put a breakpoint in the closure at this line: self.handleAppRefresh(task: task as! BGAppRefreshTask)

Relaunch your app with Xcode (no need to modify the Scheme), put your app in the background with a swipe up, and wait between 5 to 20 minutes, doing nothing else. Make sure your debugger is still attached to your app, and feel free to add print statements throughout to trace execution. Eventually, you should enter the closure and hit your breakpoint. After that, press "Continue" and wait another 2 to 3 minutes, and you should see the self.handleAppRefresh(task: task as! BGAppRefreshTask) function trigger again.

I hope this helps.

Please note that I'm using an iPhone 11 with a cable. Xcode Version 15.2

Upvotes: 1

adeasismont
adeasismont

Reputation: 285

You’ve only registered your task handler so far. You also need to schedule your background task.

Please see this guide for more information: https://developer.apple.com/documentation/uikit/app_and_environment/scenes/preparing_your_ui_to_run_in_the_background/using_background_tasks_to_update_your_app

It can be a bit unpredictable when your background task will be executed, and might not happen at all exactly when you expect it to.

This outlines how you can debug your task handlers to make sure they’re registered and have correct requests submitted: https://developer.apple.com/documentation/backgroundtasks/starting_and_terminating_tasks_during_development

Upvotes: 0

Related Questions