Implementing SwiftUI’s OnChange Modifier for iOS 13
Let’s add backward-compatibility support for the latest SwiftUI feature
With the release of iOS 14, SwiftUI gained some powerful new features. But if you're still stuck supporting iOS 13 platforms, then that doesn't do you much good, does it?
I recently needed to use the onChange
view modifier in a project, but I soon came to realise that it’s not supported on iOS 13 deployment targets. Here’s the big fat error XCode gave me:

Fortunately, there is already a simple workaround for iOS 13. Have a look at this Picker
I made below to select your favourite fruit:

Let’s say we wanted to print to the console whenever the selected fruit changes.
How would we achieve this?

We can actually use onReceive
to listen to a given publisher, and of course, you can use onReceive
Hooks dating back to as early as iOS 13.
But to create a Publisher
that listens for changes to our selectedFruit
variable, we have to wrap it in a Just
publisher. Just
is a built-in type of Publisher
that just listens to changes to a given variable. You can test this out for yourself if you’d like. You can find the full code in this gist. And you can read up about Just
publishers on Apple Developer.
Note: Just
requires Combine
, so make sure you use import Combine
.
This doesn’t make things easy for you to implement across platforms, though. You still have to manually switch between onReceive
and onChange
using @available
statements or just commit to use only the onReceive
modifier instead.
To make things a bit easier for you, I made a custom onChange
modifier that uses this onReceive
under the hood for iOS 13. But if you end up compiling for an iOS 14 target, you can take full advantage of Apple’s own onChange
modifier.
Below, you can see the definition of Apple’s onChange
modifier fetched by right-clicking on an onChange
and selecting Jump To Definition.
You can test this out in XCode yourself if you’d like:

As you might expect, there is an @available
tag above the definition specifying that this is only available on iOS 14 or above. We’re going to make our own definition close to this with implementations for both iOS 13 and iOS 14. To avoid confusing the compiler, we’ll name our implementation slightly differently. Our new backward-compatible modifier will be called valueChanged
.
The solution:
You can safely use this new valueChanged
modifier in any project on iOS 13+. Once you end up compiling for an iOS 14 target, you can be sure that your project already takes advantage of Apple’s onChange
modifier.
Thanks for reading.