watchOS: PUT request in the background

We develop a shared grocery shopping list for iOS, iPadOS and also watchOS. Users can share shopping lists between each other and the lists get automatically synced.

The user can go shopping using our watchOS app alone, as it is an independent watch app. While shopping, connectivity issues are very common, since in retail stores a reliable internet connection is very rare. This leads to the problem that sometimes changes to the shopping list won’t get synced back to our servers.

At some point after the shopping is done, we need to the sync local changes done to the shopping list back to the server. Since the app will most likely be in the background again as the user leaves the retail store, this sync needs to happen in the background (when we have a stable internet connection again). The API for this sync is a simple PUT request with a json body to send.

What frameworks / APIs should we use for this?

Firstly I wanted to use WKURLSessionRefreshBackgroundTasks. But according to this lasts year session at 09: 32 from WWDC20, no networking is allowed for this. Although, if I debug the app, the call completes. So I am confused right now. Can we perform a simple PUT request in the WKExtensionDelegate handle(:Set<WKRefreshBackgroundTask>)?

Also a lot of documentation is pointing me to use BackgroundURLSessions for doing networking in the background (also this session here from WWDC21). But BackgroundURLSessions only support download- or upload tasks. Simple dataTasks are not supported in background sessions (see here). So this is no option either...

What should I do here?

Thank you

Answered by Frameworks Engineer in 678592022

Hi Renato!

I'm a little confused about whether you need a URLSessionDataTask for your particular application. You can set the HTTP method to "PUT" on either a URLSessionUploadTask or a URLSessionDownloadTask and that will work in the background.

The distinction between a URLSessionDownloadTask and a URLSessionDataTask is the disposition the reply. For a URLSessionDownloadTask, the reply is stored to a file and your delegate callback function is called with the location of the file. For a URLSessionDataTask, the reply is stored in memory. I'm not sure if that distinction makes a difference in your use case.

If I understand your workflow, your customers are shopping. They probably don't have connectivity, but they have your great Watch app to help them remember the items on their list and navigate the store. They're marking off the items on the list, but those changes can't make it back to the server because there is no connection. So you're setting up this request to send to the server to update the list. When the shopping trip is done, you create a URL session. The body is the updates from the shopping list. You enqueue a background URL session to make the request. The system processes it for you in the background, and notifies you to handle the callbacks on your delegate (see the session information on the Extension Delegate and the URL Session Delegate). Since the content of the shopping list update is in the body of the request, your server is handling that part when it gets the URL request that the system has sent in the background. You'll get the callback on your delegate with the response from the server (if you have any error handling or other list updates that are included from your server reply, depending on the nature of the reply, that would be where that would happen). The you set the WKURLSessionRefreshBackgroundTask complete, and you're done.

I hope that helps! Thank you for building this Watch app for your customers. I know they're going to love it as you continue to make improvements.

Accepted Answer

Hi Renato!

I'm a little confused about whether you need a URLSessionDataTask for your particular application. You can set the HTTP method to "PUT" on either a URLSessionUploadTask or a URLSessionDownloadTask and that will work in the background.

The distinction between a URLSessionDownloadTask and a URLSessionDataTask is the disposition the reply. For a URLSessionDownloadTask, the reply is stored to a file and your delegate callback function is called with the location of the file. For a URLSessionDataTask, the reply is stored in memory. I'm not sure if that distinction makes a difference in your use case.

If I understand your workflow, your customers are shopping. They probably don't have connectivity, but they have your great Watch app to help them remember the items on their list and navigate the store. They're marking off the items on the list, but those changes can't make it back to the server because there is no connection. So you're setting up this request to send to the server to update the list. When the shopping trip is done, you create a URL session. The body is the updates from the shopping list. You enqueue a background URL session to make the request. The system processes it for you in the background, and notifies you to handle the callbacks on your delegate (see the session information on the Extension Delegate and the URL Session Delegate). Since the content of the shopping list update is in the body of the request, your server is handling that part when it gets the URL request that the system has sent in the background. You'll get the callback on your delegate with the response from the server (if you have any error handling or other list updates that are included from your server reply, depending on the nature of the reply, that would be where that would happen). The you set the WKURLSessionRefreshBackgroundTask complete, and you're done.

I hope that helps! Thank you for building this Watch app for your customers. I know they're going to love it as you continue to make improvements.

watchOS: PUT request in the background
 
 
Q