MVVM with RxSwift

At least we can get rid of view controller massiveness

Muhammad Ridho K. Pratama
Ridho's Personal Note
5 min readApr 6, 2017

--

image taken from here

Background

When developing an iOS application, you knew that architecture being used to develop an iOS application is MVC (Model-View-Controller), which every application component separated by their responsibility.

On the MVC architecture, Model is responsible to provide the data or controlling all of things related to data access. A Person or PersonDataAccess class is an example of the model. View is responsible to displaying the data to user interface. And, the last is a Controller which responsible to altering the model and preparing the data to be presented to the View.

Apple MVC

According to Apple MVC concepts, the View sends user action to Controller, then the Controller update the model with the data which has been sent from the View, then the Model notify the Controller about data changes in a Model, and the last is, Controller updating the View.

Look’s simple, right? But the reality isn’t same as those concept above. Most of iOS developers (includes me 😂) tend to make a Massive View Controller.

MVC reality

Why that’s considered as a problem?

Because the View and the Controller is tightly coupled and difficult to say they’re separated. And in this case, UIViewController subclass is considered as a View. So you’ll tend to write all of those responsibility (network calls, event handling, data altering, displaying the data and so on) to the View Controller (UIViewController subclass).

Seems easy to implements, but there are a lot of consequences.

  1. Hard to test the business logic, due to presentation and data manipulation combined into one layer (View)
  2. Hard to maintain
  3. Bloated UIViewController
  4. and sooooo on…

Because of all of those problem above, I’m begin to learn an alternative architecture which solved those problems.

Meet the MVVM

So here is the rescue for the view controller massiveness. There is a component called ViewModel. So, what’s the responsibility of ViewModel?

Like a Controller on the MVC architecture, ViewModel responsible to altering model and preparing the data to be presented to view. But, there are many differences. ViewModel provide data binding mechanism to the View, so if there’s a data changes on the ViewModel, the View will be updated automatically and the ViewModel have no references to the View.

MVVM architecture

Personally, I like this architecture because of a data binding mechanism, so the View can updated itself if there’s a changes at ViewModel, and easy to test the model and business logic, because of separation of a responsibility.

So, the benefits of MVVM when applied to iOS development is

  1. easy to test a business logic & model
  2. view is almost passive, because of data bindings, altough we’re still use view controller to perform a segues (homework, separate this 😂)
  3. easy to change the UI without messing a business logic
  4. you can put your business logic or your network call to the ViewModel, so view controller become a less bloated

Rule of Thumb of ViewModel

  1. No reference to view
  2. No import UIKit
  3. No reference to any UIKit‘s components, likeUIView , UIButton , UITextField , and so on
  4. Just a data. JSON, dictionary, or other data structures

RxSwift

A reactive programming framework provided by ReactiveX. This is a Swift version of Rx. It relies on observable pattern, if there’s a data changes or event from Observable, the Observer can perform something. More details of RxSwift is found here.

Here, I use RxSwift on MVVM architecture to provide data bindings from ViewModel to View, and notify the ViewModel if there’s a changes on the Model.

Talk is cheap, show me the code!

You can visit my github repo here to get a better understanding about implementation of MVVM + RxSwift. I’m going to explain an important classes from that project

Model

Explanation :

  1. On the line nr. 7, I declared a variable named todosFromCoreData that can be observed by ViewModel. And on the line nr. 8, managedObjectContext variable is an object which used to storing a NSManagedObject objects (as a part of CoreData framework).
  2. Initializer is used for fetching data from core data when there’s an object instantiated from that class
  3. Data operation, such as fetching todo, add todo, remove todo, or change todo. After altering data, we must re-fetch updated data from persistent storage.

ViewModel

So, in a ViewModel, I have a 3 members:

  1. todos : is used for binding sources to the view
  2. todoDataAccessProvider : is used for altering data from model
  3. disposeBag : part of RxSwift, for memory management purposes. More info can be obtained here

Method fetchTodosAndUpdateObservableTodos() is used for subscribing an observable todos from TodoDataAccessProvider class, if there’s an update from it, then todos will be updated accordingly.

Line 30–42 is used for handling events from the View, such as add todo, delete todo, and toggle todo. I just call the method from todoDataAccessProvider to changing the model.

View

On line nr. 9, I have a member that instantiated from TodoListViewModel , then take a look to viewDidLoad() method.

On the line nr. 18, there’s a call to populateTodoList() method which perform a bindings from ViewModel to View, then render it to UITableView .

Then on the line nr. 19, there’s a call to setupTodoListWhenTableViewCellTapped() which perform an action when item has been selected via reactive wrapper to a table view delegate. Call toggleTodoIsCompleted(withIndex:) from todoListViewModel .

Then on the line nr. 20, there’s a call to setupTodoListWhenTableViewCellDeleted() which perform an action when item has been deleted via reactive wrapper to a table view delegate. Call removeTodo(withIndex:) from todoListViewModel .

And the last, an @IBOutlet buttonAddTodoTapped(_:) is used to handling event to adding Todo, and call addTodo(withTodo:) from todoListViewModel .

Testability & Conclusion

A View layer now less bloated because there are a binding mechanism to ViewModel, and View just observe the changes from ViewModel. Now, ViewModel or Model can be tested easily 😉

What’s next

I hope you’ll understand about how to implement MVVM architecture in your next project, if there’s something that can’t be understood, let me know in the comment. Cheers.

--

--