2019 WWDC really surprised a lot of iOS developers in the world. One of the things that have been drawing my attention was "SwiftUI and Combine". As all iOS developers knew, in day 1, we have to deal with problems like difficult languages, interface constraints setting, storyboards merge conflict, massive view controller, untestable viewcontroller for years. They delivered solutions from day 1 until now to solve the above mentioned problems. This year, they announced SwiftUI. SwiftUI basically changes everything again. At first glance, it seems Apple turns every iOS experts from hero to zero. Quite the contrary! It makes it a lot easier to implement the Reactive MVVM pattern. Before showing some experiments, we have to understand why MVVM and Reactive programming are playing a big role in modern iOS.
MVVM (Model-View-ViewModel) is widely used in nowadays mobile app development. The "Model-View-ViewModel" design pattern is similar to "Model-View-Controller". However, iOS invented a combined roles of View And Controller – UIViewController.
This lead to a huge problem of maintenance in a long run. In my personal experience, it is very difficult to separate the business logic out of the UIViewController, it turns out that the UIViewController is difficult to have solid unit tests. Also, in each of UIViewController, it has its own view life cycle, meaning it will change its state during the time. While you have to write a unit test for that, you have to care about the UIViewController state. Sooner or later your MVC design pattern no longer stands for "Model View Controller" but "Massive ViewController".
MVVM is one the solution to decoupling the UI and business logic out of the massive UIViewController, make it much more testable and reusable. MVVM is built from three fundamental parts View/ViewController, ViewModel and Model.
Model - a data model class that owns properties for data.
ViewModel - a class that contains business logic to update model and update the view/ViewController
View/ViewController - a class that contains mainly UI elements or components
In reality, updating model data could be in an asynchronous process (e.g. request API). How could you retrieve the data and then notify the view part? There is one rule: ViewModel DO NOT have any reference to any View/ViewController (no reference to UIKit). It means ViewModel should not own any View/ViewController. So here is a problem: how could you possibly update model and view at any time without holding any view/ViewController instance in ViewModel?
There are several ways in iOS SDK to communicate between models and views:
However, this will create a lot of code for the event - a callback mess. And apart from block, the other three methods are difficult to chase through the hierarchy of calls. Therefore, we have to use binding to map the data from ViewModel to View/ViewController. Of course, we can use KVO and notifications for mapping data between view and view model, but they aren't first choices for binding. There are many available tools for that binding purpose. We can achieve the data binding purpose by:
In this blog series, we will mainly focus on the Reactive Programming Framework.
Why Reactive Programming Framework?
There is a tone of information in the internet to tell you what Reactive Programming is. I am not going to tell what, but why. While we talk about implementation of MVVM, one big benefit of using MVVM is separating the business logic and the UI in the code base, so that it is much easier to test and reuse it. However, it will create a lot of overhead in events and callback handling if you’re not using reactive framework. In reality, there would be tones of delegates, blocks, observer-notifications firing around the app.
We have two tasks while we implement the MVVM pattern: on the one hand, we have to extract the business logic from View/ViewController to ViewModel, on the other hand, we have to minimize events and callbacks clutters. Therefore, the reactive programming framework provides a better solution to maximize MVVM benefits during the development process.
There is one popular third-party framework called RxSwift which provides data-binding technology. Also RxCocoa is an extension of UiKit, it helps developers more effectively and easily to implement with RxSwift. Combine is a new library from Apple, which provides similar functionalities as RxSwift.
In the following blogs, we will try to implement a little project in reactive MVVM pattern with RxSwift and Combine.