Update Watch Complication with CloudKit

I have an iPhone app the uses CloudKit for Core Data syncing. I also have a companion Apple Watch app that syncs to the same CloudKit records. The watch can be used without the iPhone app as well but they both independently sync to the same CloudKit database. This works reasonably well. As soon as either app is opened, the CloudKit will pull down the latest records.

I'd like to add a watch complication that shows the state of the CloudKit records. I supported this by adding a Widget extension, embedded in my watch app. The Core Data database in the watch app is part of an app group, so the complication is able to query the same database. So far so good.

I'm running into problems with the complication updating after remote records are changed from the iPhone. Here is what is happening:

  • When records are changed on the iPhone, the data syncs to CloudKit but the watch app is not updated when in the background. This is noticed when you open the app and it takes a second for the view to show the new records.
  • Since Core Data database on the watch is not being updated while in the background, the complication is not being updated at all.

Part of my confusion is I assumed CloudKit was meant to make this more seamless with silent push notifications? I have the "Remote Notifications" capability enabled on my WatchApp. It seems that only works while the app is in the foreground though. This seems very limiting when you have a complication that depends on the Watch app's Core Data state.

I have a few things to work around this with mixed success:

  • "Wake" the watch app explicitly when records are changed on the iPhone app using WatchConnectivityManager. The hope is that by waking the watch app, it will sync with iCloud. This either isn't working or intermittenly works. It is also not clear to me that by activating the watch app, that it will trigger records to sync. I wish there were a way to ask Core Data to sync explicitly.
  • Whenever the Apple watch app wakes in the last step, ask it to WidgetCenter to reload the widget.

This process feels convoluted and seems to negate some of the the benefits of CloudKit to synchronize data which I thought would be baked into this process.

Any thoughts on a better approach to all this?

Answered by pilotcoder in 753252022

My work around for these slow Core Data sync issues is to use the CloudKit API directly from the complication. It seems that about every 5 minutes the complication requests an update so it stays reasonably updated with whatever is in CloudKit.

When you use the WatchConnectivityManager, do you update the applicationContext on the main thread? If not, that may be part of your connectivity problem.

Accepted Answer

My work around for these slow Core Data sync issues is to use the CloudKit API directly from the complication. It seems that about every 5 minutes the complication requests an update so it stays reasonably updated with whatever is in CloudKit.

How are you using CloudKit API directly from the complication? My impression was Core Data for CloudKit handles all the syncing and does not expose interfaces to mange it directly. I'm facing similar issues with watchOS app staying in sync with data in CloudKit.

Update Watch Complication with CloudKit
 
 
Q