How to create a Combine pipeline to react to @Published properties in SwiftUI

Pipes representing data flow


Have you ever wondered how to create custom actions based on @Published properties in your SwiftUI code but have no idea how to do it? Have you been stuck trying to write SwiftUI lifecycle functions, but they aren’t cutting it for your needs? Today, we’re going to be learning how to react to published properties by subscribing to their publishers!

A common example of a needed publisher subscription is the property value changes and you want to have an action performed when that value changes. E.g. reacting to a button change or even the value entered in a text field. Your reactive action could be very simple or it could be extremely complex. Either way, they both follow the same underlying principles.

So, let’s get into it and learn how to create your own custom combine pipeline for @Published values! 🍾

Getting the publisher

Before we can react to the published values, we need to get the publisher so we can subscribe to it. Thankfully, since we’re using an @Published property, getting the publisher is as simple as putting the $ in-front of it. An example can be seen down below ⬇️

@Published var score = 0

// this is the publisher

We can now use combine to create a pipeline for this publisher and the emitted values. How easy is that!

Creating a custom pipeline

Since I believe the best way to learn is by practice and seeing real-world examples, I’m going to walk you through a problem that I encountered recently. I had a password TextField that I wanted to spruce up and give some flare for the user so they could feel an interaction when signing up for an account in my app.

Basically, as the user typed in their password I wanted to set the border color to red, yellow, or green based on their password “strength”. This is a perfect scenario to use combine because we’re reacting to the change of password with every character that the user enters or deletes. Without combine, you would have to use the onCommit callback but that only gets called when they hit enter.

What good is that for knowing your password is 🗑️ after they’ve already entered it? It’s not. So let’s jump in an do it the right way!

NOTE: Before we get started, if you aren’t familiar with combine, I highly recommend you check out this combine manual.

Since I wanted to react to the changing password string, I‘m going to subscribe to the publisher and then provide a pipeline for the emitted value to go through. Since we’re looking at updating a color property based on some “security score” our pipeline might look something like this: map the password to a score value, map the score to a Color, and then assign the color to passwordRectangle color.

That pipeline would look something like this:

      .receive(on: DispatchQueue.main)
      .map {
            self.securityScore(for: $0)
       }.map {
            self.borderColor(for: $0)
       .assign(to: \.borderColor, on: self)
       .store(in: &cancellableSet)

As you can see we receive the emitted value on the main queue (because we’re updating the UI), we then map the updated value -> security score, next we map the security score -> color, and then finally we assign that value to the borderColor value. We then store the returned cancellable in our cancellable set so we can cancel the subscription at any time!

It’s also important to note that borderColor is a @Published property. We do this because we want the UI to update when the value changes and a @Published property will do this for us!

As a result of the pipeline we just created combined with the @Published borderColor, your TextField will now react to the entered password and change colors to enchant the user into signing up for your app 🧞‍♂️ (well, I’m kind of exaggerating that but you get my point)!

Now all we have to do is wrap this in a function and call it during init or you have a view call it during onAppear. It’s really your call and will be based on your needs. In my case, I placed the subscription to the publisher during the initialization of the view model.

Wrap Up

Today we learned how to create a Combine pipeline for @Published variables so we can react to their state changes in a custom way. As a result of this, we were able to create an awesome pipeline that changed the PasswordTextField border to a different color based on the strength of the password entered.

Being able to use Combine to its full potential is in my opinion, the key to the feature of SwiftUI programming. Combine allows us to create extremely complex data pipelines that are human-readable and not challenging to understand. Consequently, we decrease the number of errors in our code and react to more changes thus giving the user a better app experience! 👩‍💻

Comment down below👇 how you’re looking to use/ already using Combine in your project.

As always, if you liked today’s content, make sure you subscribe to the newsletter down below and if you want to support my coffee addiction, help me out by buying me a coffee! It keeps me going to create more AWESOME FREE CONTENT FOR YOU! As always, thanks for taking the time to unwrap some bytes with me. Cheers! 🍻

Success! You're on the list.

Photo by tian kuan on Unsplash

Leave A Comment