You should use Combine for View-ViewModel binding in your iOS app
The MVVM (Model-View-ViewModel) architecture has got increasingly popular in the past few years following the need to break down the responsibilities of a view or a
One common way to listen for ViewModel changes from your view is Binding.
In this article, I’ll try to convince you to use Apple’s (not-so-new-anymore) Combine framework for you View-ViewModel binding :)
Essentially, data binding and View-ViewModel binding in particular is a way to reflect changes to the view model immediately on the view (our UI). This is achieved by observing the property on the view model and calling some kind of callback once it is changed.
If you have experience with MVVM binding in iOS, you may have used a class similar to this one:
While this may be a good solution, using Apple’s Combine framework can be a much better approach. Let’s explore how and why you should use it!
In the heart of Combine are Publishers and Subscribers. Publishers expose values that can change over time and Subscribers receive those values from the Publishers. This is also the core of SwiftUI’s reactive nature.
The easiest way we can create a Publisher is by wrapping a property with the
@Published property wrapper. This will attach a publisher to our property, which we can access using
$ . For example:
@Published var currentTemperature: Double = 16.2print($currentTemperature) // prints "Publisher(subject: Combine.PublishedSubject<Swift.Double>)"
Publisher has a lot of interesting abilities, but what we are really interested in is the
This method will attach a subscriber to our publisher, reporting changes in a closure — very similar to our old Binding example from before.
Let’s look at an example:
cancellable constant we created is an instance of Combine’s
AnyCancellable type, which for our purpose is some kind of token we need to store in memory for the binding to be kept alive.
In a classic ViewController we will see it usually in the following form:
Great! Now that we established a binding pattern using Combine, let’s talk about its benefits, or in other words, why we did it in the first place?
1. Usage of Combine’s Operators
Combine’s Operators lets us act-upon or transform the received value before receiving it on the Subscriber’s end.
For example, we can use the
dropFirst() operator to ignore the first, or first
n callbacks. That’s useful if you don’t need the callback to run upon calling
viewDidLoad(), for instance.
An even simpler example would be using some of Combine’s built-in operators like
reduce which are very similar to the Swift’s standard library high order functions. Let’s see how we can easily get callbacks that return only a temperature that is above 5 degrees and is nicely formatted, in our weather example:
You can also write your own custom operators. For example, this is a custom transformation operator that returns a tuple including both the new and the old value, making use of Combine’s
2. Multiple Subscribers
Binding is not only restricted to MVVM scenarios!
For big apps with complex states and architecture, multiple bindings to the same property could be a major benefit.
Let’s visit the simple example below where both a ViewController and a different service class listen to the same property in a shared manager class:
3. No Extra Code, Managed and Maintained by Apple
While you can work around to implement the benefits above in a custom Binding implementation — why would you do that?!
Aside from memory management and code organization issues you could face implementing your own, Combine’s functionality is handed to us free, both on UIKit and SwiftUI.
Combine is an awesome framework we should embrace and not be scared of!
That is it for now!
I hope you learned something from this article. Please feel free to ask questions or comment about anything that triggered your mind :)