Combine not working in background tasks on watchOS 26

I have several combine pipelines in my watch and iPhone app. While background tasks on the iPhone work correctly (the combine pipelines all activate), on the watch the pipelines do not get activated. I have an internal log reporting that data is being fed to the sources but is not propagating to the sinks.

Thoughts?

Which "BackgroundTask" type are you using? The SwiftUI BackgroundTask API actually works by aggregating the behavior of a number of unrelated APIs, only some of which are public or fully supported on watchOS. That makes it very difficult to talk about it in a "generic" way.

*It doesn't help that we've used the term "background task" for two OTHER APIs (UIApplication.beginBackgroundTask() and the BackgroundTask framework), both of which are significantly older than the SwiftUI API.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Well I tried both styles. The initial code was the swiftui .backgroundTask modifier which worked in iOS 18.

I created a core data based logger to see where the hiccup was. I noticed data was indeed being read by the anchored queries from HealthKit. That data was then sent to a couple of published properties in observable objects which served as the start of the combine pipelines.

In ios18 that led to updates that were critical for updating widgets. In iOS 26, the combine pipelines were not activated.

So I switched back to the previous method of background tasks, ie wkapplication.scheduleBackgroundRefresh(...)

That also did not allow any combine pipelines to happen.

In the end, I had to rip out combine from the watch and use didSet and custom handler blocks. While that did work, obviously it's not as full featured (ie, you can't debounce). After using blocks, things went back to functioning properly.

Thoughts?

In the end, I had to rip out Combine from the watch and use didSet and custom handler blocks. While that did work, obviously it's not as full-featured (i.e., you can't debounce). After using blocks, things went back to functioning properly.

Thoughts?

That this is what I don't like about things like Combine...

Now, I'll freely admit that one of the realities of working in DTS is that spending all of your time working on other people’s problems makes it hard to be optimistic about, well, just about anything.

However, the promise of technology like Combine is that it makes code easier to write and maintain by reducing "boilerplate" and "unnecessary" code. The problem with a technology like Combine is that when something goes wrong, it's very hard to figure out what failed or how to fix it.

Unfortunately, the dynamic I've seen over and over again across many APIs designed to make things Better™ is that lots of apps end up falling into one of two "traps":

  1. The problem itself is simple enough that the "easy" technology is just making everything more complicated than it needs to be. Relying on an elaborate invisible notification architecture to avoid calling a couple of methods is not a good trade-off.

  2. The app is sufficiently complicated that the "easy" technology ends up hiding so much of the app’s logic flow that it becomes impossible to understand how the app actually works.

For the first case, the basic question is simply "does this actually make my app better". If it doesn't ACTUALLY make things better, then don't use it. If you're going to use it, then the "art" here is finding the right balance between the "magic" the API provides and having sufficient architecture that you can "manage" how your app actually works.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Combine not working in background tasks on watchOS 26
 
 
Q