BGTaskScheduler on Mac Silicon not scheduling

When I register & schedule a Background Task on an iPad, it runs properly. Running the exact same code on an M1 MacBook Pro, though, never schedules the task. There's no error, just a failure to schedule. After scheduling and calling getPendingTaskRequests, on the iPad you can see that it has a pending task, but not on the Mac. Why would this be?

BGTaskScheduler.shared.register(forTaskWithIdentifier: taskIdentifier, using: nil) { [self] task in
            print("task to run")
}

do {
   try BGTaskScheduler.shared.submit(request)
   BGTaskScheduler.shared.getPendingTaskRequests { [self] tasks in
      print(tasks.count) //Prints 1 on iPad, prints 0 on Mac
   }
} catch {
   //Code never comes here.
   print(error)
}
Answered by DTS Engineer in 792209022

After scheduling and calling getPendingTaskRequests, on the iPad you can see that it has a pending task, but not on the Mac. Why would this be?

So, the short answer is basically "because it isn't really implemented and doesn't really work". There are a small number of frameworks (CallKit is another example) that were included in MacCatalyst (and the iPad compatibility layer) but that don't actually function on macOS. You can call the APIs and they'll "succeed" (meaning, nothing will crash) but they won't actually do what they'd do on macOS.

The longer answer (and this is true of most of the other frameworks as well) is the semantics of how macOS works are SO different than iOS the functionality just doesn't really make sense. Looking at BackgroundTask in particular, comparing how macOS works:

-macOS provides a FAR broader range of options about how apps "do their work" than iOS does. Notably, running code "in the background" is straightforward on macOS and very involved/difficult on iOS.

-On macOS, the user manages apps much more directly and (in general) does NOT expect the system to launch apps "behind their back". There are mechanisms the system uses to launch apps without direct user interaction, but all of them are within the users control.

-macOS has a much more complicated "device" life cycle. An iOS device is basically "on" or "off". A macOS device could be logged in as a one user, many users, or none, with sleep/wake layered on top of that.

-On macOS, app lifetime is more visible to the user AND the user expects to have much more direct control over that lifetime. The approach iOS uses doesn't really "work" within macOS's design, as it would mean that the system was launching apps at relatively "arbitrary" times without providing a mechanism to manage control them.

That combination of factors are why it isn't currently implemented- it's not just that the iOS approach doesn't match macOS, it's ALSO that macOS apps already have ways to solve this problem that are FAR more flexible than what's possible on iOS.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Accepted Answer

After scheduling and calling getPendingTaskRequests, on the iPad you can see that it has a pending task, but not on the Mac. Why would this be?

So, the short answer is basically "because it isn't really implemented and doesn't really work". There are a small number of frameworks (CallKit is another example) that were included in MacCatalyst (and the iPad compatibility layer) but that don't actually function on macOS. You can call the APIs and they'll "succeed" (meaning, nothing will crash) but they won't actually do what they'd do on macOS.

The longer answer (and this is true of most of the other frameworks as well) is the semantics of how macOS works are SO different than iOS the functionality just doesn't really make sense. Looking at BackgroundTask in particular, comparing how macOS works:

-macOS provides a FAR broader range of options about how apps "do their work" than iOS does. Notably, running code "in the background" is straightforward on macOS and very involved/difficult on iOS.

-On macOS, the user manages apps much more directly and (in general) does NOT expect the system to launch apps "behind their back". There are mechanisms the system uses to launch apps without direct user interaction, but all of them are within the users control.

-macOS has a much more complicated "device" life cycle. An iOS device is basically "on" or "off". A macOS device could be logged in as a one user, many users, or none, with sleep/wake layered on top of that.

-On macOS, app lifetime is more visible to the user AND the user expects to have much more direct control over that lifetime. The approach iOS uses doesn't really "work" within macOS's design, as it would mean that the system was launching apps at relatively "arbitrary" times without providing a mechanism to manage control them.

That combination of factors are why it isn't currently implemented- it's not just that the iOS approach doesn't match macOS, it's ALSO that macOS apps already have ways to solve this problem that are FAR more flexible than what's possible on iOS.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

BGTaskScheduler on Mac Silicon not scheduling
 
 
Q