Data Binding in MVVM on iOS

Fitzgerald Afful
4 min readApr 28, 2020

--

You’ve come to realize your View Controller in your new project has become very huge. Too much spaghetti code in there. That’s what they call the ‘Massive View Controller’. In trying to restructure and refactor your code, you learn about Design Patterns. VIPER, MVVM, VIP, and the rest. You think MVVM will suit your needs and it will be fun learning that so you decide to try that out.

… well, until you come across these basic rules of the thumb on MVVM

  1. View Model is owned by the view and the model is owned by the view model.
  2. View Model is responsible only for processing input to output and logic required for driving the UI.
  3. View Model should not modify the UI.

That means the View Model and the View Controller should find ways of alerting each other. In comes Data Binding.

Data Binding is simply the process that establishes a connection between the app UI (View Controller) and the data (Not Model, But View Model) it displays. There are different ways of data binding so we’ll look at a couple. Please note, that Data Binding does not apply only to MVVM but to other patterns too.

Technique 1: Observables

This appears to be the easiest and most commonly used. Libraries like Bond allow you to bind easily but we’re going to create our own Helper class called Observable. It’s initialized with the value we want to observe (or pass around), and we have a function bind that does the binding and gets us our value. listener is our closure called when the value is set.

Let’s move to our ViewModel. Before we focus on our numbered lines, all we’re trying to do here is get our ViewModel to implement the Protocol we created for it, then fetch data (Employees) from our APIManager class.

//1 is how we declare our Observable on our Employees array in our protocol. //2 is how we implement //1 in our ViewModel. And finally //3 is we set/add data to our Observable. We can now go ahead to bind it to viewDidLoad in our View Controller.

Tadaa. Anytime employees are added or set, self.showTableView will get called in our Controller.

Technique 2: Event Bus / Notification Center

EventBuses are more popular on Android. On iOS, they are well-structured wrappers for the NotificationCenter. You can go for César Ferreira’s SwiftEventBus or this refactored version (which I use).

  1. Create an Event that will be pushed by the EventBus to all subscribers. It usually contains the stuff we want to pass around. So EmployeesEvent contains our employees, error Boolean and errorMessage String.

2. Publish (Or Post) the Event from the ViewModel using the EventBus.

3. Subscribe to Event from View Controller. So setupEventBusSubscriber is called from our viewDidLoad.

Contents of our EventBus’ onMainThread implementation run every time callEvent is called in our ViewModel.

Technique 3: FRP Technique (ReactiveCocoa / RxSwift):

The Functional / Reactive Programming approach. You can either go with ReactiveCocoa or RxSwift. RayWenderlich does a good analysis of both here, you might want to check out. But for the sake of this project, I’ll use RxSwift.

Similar to our Observable technique, our ViewModel looks like this:

The employeesproperty like the error and errorMessage variables are computed variables that return Driver (An Observable that our controls in our Views will bind to) from each of their respective private properties. (Dont forget to import both RxSwift and RxCocoa — You can add their dependencies using Cocoapods, Carthage or Swift Package Manager).

And Controller:

In the Controller, we have our DisposeBag, a RxSwift object that aids in releasing any references they may have to any observables they’re observing. setupBindings method is to observe the employees property from the View Model. Whenever employees is updated, showTableView method is called to reload the list.

Technique 4: Combine

The Combine framework (added in Swift 5.1) provides a unified publish-and-subscribe API for channeling and processing asynchronous signals.

  1. We make a publisher (in our ViewModel): To do that, we import Combine and let our ViewModel inherit from Combine’s ObservableOject. Our employees array which we want to observe will then be wrapped with a @Published property wrapper. This publisher emits the current value whenever the property (employees) changes.

2. Then, attach a subscriber to the publisher (in our View Controller): In bindViewModel, we subscribe to $employees using one of Combine’s default subscriber keywords — sink, and it allows us to update our view only when specific published properties change.

And We store the subscriber in an instance property so that it is retained (and so that it will be released automatically at the latest when the surrounding instance goes out of existence) or canceled by ourselves.

Data binding is definitely worth it when understood and used right. And with the introduction of Combine by Apple, it feels official and more iOS Developers are picking it up even though it has been popular on other platforms for a while.

It is also important to note that almost all techniques for data binding use the Publisher-Subscriber pattern. All techniques mentioned in this article are used in a very simple project on Github:

--

--

Fitzgerald Afful
Fitzgerald Afful

Written by Fitzgerald Afful

Book reviews, flash fiction and random rants about iOS Eng. Portfolio: fitzafful.github.io

Responses (8)