I've implemented background refresh in my WatchOS app, its purpose is to get some data (always less than 400 bytes) from the server at a minimum of every 15 minutes and update the complication.
Sounds pretty straight forward and it's like clockwork - works really well when I'm debugging the WatchOS app in Xcode or started by launching it manually.
The problem begins if I do something to force the system to kill the app by simply swiping through all the watch faces, or loading other apps. This is a highly realistic scenario.
At this point I switch to observing what is happening on the watch by viewing the console output:
WatchOS launches my app in the background and my extension's handle() method is called
This in turn invokes my code which creates a properly crafted URLRequest which is then passed to a background URLSession's download task.
The very small (<400 bytes) file is downloaded. This works every time, regardless of how the app is launched.
My URLSessionDownloadDelegate's urlSession(_ downloadTask:didFinishDownloadingTo:) method is NOT called, even though the file has been downloaded successfully!
Even stranger, the delegate method IS then called only if I then tap on my complication which launches the app.
Please tell me that this is not how the intended functionality is supposed to work. How am I supposed to update the complication in the background if the only time I can process the downloaded data is if the user starts the app?
I was under the (hopefully not mistaken) impression that if I have my app's complication on the Watch face I would be able to process the result and update the complication data in the background. Is that a wrong impression?
If I am mistaken, then the complication cannot be updated 4 times per hour, and what is the point then of downloading the data in the background if the user then has to tap on the stale complication?
Thanks in advance,
Sal
WatchOS 7 appears to have a better scheduling algorithm than WatchOS 6. Can't prove it though.
If my app has died and WatchOS starts it, although the scheduling of the background refresh still happens, the URLSessionDownloadDelegate's urlSession(_ downloadTask:didFinishDownloadingTo:) method is NOT called until the user either taps on one of my complications or starts the app from the home screen.
The times which I've observed skips in refresh, and my complication now says it's been over 15 minutes long is because a network error such as a timeout has occurred.
It appears that keeping a reference to the latest URLSession is worth doing, just ensure that you remove the reference when it has completed successfully or otherwise.
Using earliestBeginDate had a detrimental effect on my app. It would keep getting terminated by the system as soon as I resumed the first URLSession.