Thanks Kevin!
how do you "know" that? And what other devices have you tested on? That particular device does NOT have a dynamic island, so starting a task doesn't necessarily have any "visible" impact. The task DOES start, but you won't see any system UI unless the app is backgrounded or there are other tasks active.
The user shared a screen recording where tapping the start processing button did not start processing (which I have not replicated on my devices). Reviewing the code, I'm quite positive the only way that's possible is if the register launchHandler is not invoked nor the catch block entered from submitting the request because when one of those occurs, I present in-app UI that shows progress in addition to updating the background task progress (if non-nil) in the implementation of the startProcessing() func which didn't get called because in-app UI did not appear in the screen recording.
If your user is willing to help, what we really need is a sysdiagnose.
I asked them but they said the issue is no longer occurring 😮 I inquired if anything had changed, any device settings, low power mode enabled state or anything like that, but nothing they can think of. I suspect no one else is going to reach out to report the issue because I quickly put a workaround in place to call startProcessing(backgroundTask: nil) if it is not called within 1.5s of submitting the request. 😅
Remember that taskIdentifier needs to be unique to each task. If you try to run the same ID "again", the second submit won't work.
Yes they are unique.
Similarly, if you're running multiple tasks, make sure that startProcessing() accounts for that and can track "all" of them.
I don't support running multiple tasks simultaneously, after one completes the user could start another one if desired.
it's certainly possible that there's an issue (or bug) with their particular device configuration. One thing I would check here is "Settings.app-> General-> Background App Refresh". That setting is tied to the BackgroundTask framework, and it's possible that disabling it would also disable BGContinuedProcessingTask.
Testing this on my devices, when I turn off Background App Refresh, the register launchHandler is still called immediately. If there were an issue with the device configuration, wouldn't the submit request throw an error since the strategy is set to fail if it can't be started immediately? Or are there scenarios where it's expected behavior for an error to not be thrown and yet the launchHandler won't be called?
your app doesn't actually have to wait for the request to fire before it starts its work ... If your app is going to do the work "no matter what", then waiting for the handler to fire is just adding additional complexity, delays, and testing load. I'd start the work "immediately" and update BGContinuedProcessingTask if/when it starts.
For my simple use case it seems much more straightforward to perform the work once the launchHandler is invoked (or if the submit request fails perform the work without a BGContinuedProcessingTask). I can directly pass a BGContinuedProcessingTask or nil to the function that does the work, as opposed to needing to persist the BGContinuedProcessingTask when it starts and clean it up upon completion/cancelation/failure. This also avoids a seemingly complicated scenario: what do you do if the register launchHandler is invoked after its work had already completed/was canceled/failed, unclear what you'd do with that BGContinuedProcessingTask, shouldn't persist it, there's not a way to "cancel" it. State management for that seems very complicated. Tis much more straightforward to set the strategy to fail and begin processing once it starts or fails to start, since one of those is supposed to happen immediately when strategy is .fail, and that's a totally valid approach for using this API, is was what I understood.