ViewModel in RxSwift world

According Wikipedia view model is an abstraction of the view exposing public properties and commands. Instead of the controller of the MVC pattern, or the presenter of the MVP pattern, MVVM has a binder. In the view model, the binder mediates communication between the view and the data binder.[clarification needed] The view model has been described as a state of the data in the model.

When entering Rx world prepare to think about: UI events, Network requests, Data base request etc. as a Streams .

Keeping this in mind I like to think about ViewModel as a “Black Box” which accepts some UI triggers (button tap, table view selection, text editing events etc.), other dependencies (NeworkService, DataBaseService, LocationService) and apply some Rx operators (which determines business logic). And after that, from view model you can get that transformed observables and bind them back to your UI to apply your business logic.

As example I want to show how you could implement list of searchable data and display it in table view with search bar

Let’s imagine that all model staff implemented and all we need to do is create ViewModel and ViewController

So, let’s define UI triggers:

  • search trigger (user can type to search data in the list)
  • scroll triggers (user can scroll to pull new data from the list)

Now we can define ViewModel interface

Now let’s define transformation we want to apply to our initial triggers

  • transfrom search query into request
  • prevent firing request for empty query
  • prevent fire reqest every time user type new character
  • cancel previous request in favor of new one
  • hit request every time user scrolls to the bottom edge of scroll view
  • append previous state (array) with new data

Implementation of transformations:

  1. Filters empty string, remember we don’t want fire request for empty query
  2. Prevents to fire request every time user types new character, fires only if there is 0.3 sec pause
  3. Transfroms search query into request and cancels previuos
  4. Transfroms Hero into dummy HeroCellData (eg. title, image url)
  5. Transforms Array of HeroCellData into HeroCellSection (this needed to bind it to the the UITableView)
  6. Triggers next page request

And now let’s bind our transformed Observables back to UI

  1. Create ViewModel
  2. Bind Main table items to UITableView
  3. Bind search items to the UISearchController’s tableView

Summary:

  • Our view model is “pure” it’s immutable, we don’t even need a reference to it in ViewController (the disposeBag keeps subscriptions alive)
  • All logic incapsulated in one place
  • It’s can be easily tested with RxTests . Coming up in the next article :)

Further reading:

Happy RxSwift coding! :)