iOS Architecture: MVVM-C, ViewModel’s (4/6)

Daniel Lozano Valdés
Sudo by Icalia Labs
4 min readOct 4, 2017

What is a ViewModel?

Let’s have a thought experiment. Take a typical view controller and split it into two parts. On one side leave all of the UIKit/UIViewController specific methods and everything that deals directly with views and subviews. And on the the other side put everything else, all of your business logic; i.e. network requests, validation, preparing model data for presentation, etc…

So basically, the former part (UIKit stuff) will remain, as it should, in the view controller. Everything else, all of app specific business logic, will now be in the ViewModel.

This separation helps the view controller adhere to the single responsibility principle. Now the view controller which is a part of UIKit as it’s a UIViewController subclass only deals with UIKit stuff. Handling rotation, view loading, constraints, adding subviews, target actions, etc.

This leaves the ViewModel totally clear of UIKit land. Which let’s it focus on the core business logic, adhering to SRP. This makes it much easier to reason about and to test, among other things.

The ViewController will have a one-to-one relationship with the ViewModel. There will be one ViewModel per ViewController, and the ViewController will own it’s ViewModel. By that I mean that it will own a strong reference to it’s ViewModel, but it will not create it itself, it will get passed on to it via dependency injection. In our case, it will get created by the Coordinator and passed on to the ViewController.

Let’s see some code

First step for creating a ViewModel is defining a protocol. ViewModel’s should be protocol based because when you inject the ViewModel dependency into the view controller we don’t want to depend on a concrete type. This let’s us experiment with different implementations, for testing or other purposes.

Protocols

There should usually be three protocols:

  • YourNameViewModelType: This is the protocol that our ViewModel’s should implement. It is conformed of two main parts. The Data Source which will have all the formatted data the view controller needs, and the Events which are events that the ViewController will send up to us on any user action.
  • YourNameViewModelCoordinatorDelegate: This delegate protocol will let us bubble up any action’s that we can’t handle and must be handled by our coordinator. This delegate should be set by the coordinator when it creates each corresponding ViewModel.
  • YourNameViewModelViewDelegate: This delegate protocol will let us communicate with the ViewController. Whenever we have new data for example, we let the ViewController know so it can update it’s screen. Since the view controller owns the ViewModel we don’t want to create a reference cycle by holding onto a strong reference of the view controller. So we have a delegate which is set by the view controller to itself when the ViewModel gets injected into it.

If you choose to use a framework like RXSwift or ReactiveCocoa to do Funcional Reactive Programming, then the ViewModelViewDelegate protocol and the event methods inside the main protocol would not be needed because all two-way communication between your ViewModel and ViewController would happen via those frameworks. But those topics are beyond the scope of these articles. I personally think that this is a good way to architect this without having to introduce any other foreign concepts, at least for now.

Implementation

Let’s look at our sample implementation.

In this previous code we have three important parts:

  • We have several properties which include both our delegates, our data models, and a service layer object. (More on services next)
  • We have an init method in which we should get all the dependencies we will need. In our case it’s the Place service which will let us do network requests.
  • An example of network requests that would happen in the ViewModel, and how we would use the viewDelegate to let the ViewController to update it’s screen to reflect the new available data.

Data Source & Events

Besides all our business logic like network requests in this example, we need to implement the ViewModel’s protocol.

  • The Data Source methods will handle formatting any model data the ViewController might ask for. We don’t want to send any model object directly to the View layer so usually we will only return formatted String’s or other struct’s like ViewData’s (More on that next).
  • The Event methods will get called by the ViewController when there is a user action and we need to do something about it. Sometimes we will need to kick off a network request, or sometimes if it’s a navigation issue we will need to bubble it up to the coordinator via the coordinatorDelegate.

ViewController

So how will this look from the ViewController side? Let’s see some code. I cut most of the code out of the example just to show you the basic idea.

A couple of important points in this example:

  • We have a strong reference to the ViewModel and we have a didSet listener ready to set ourselves as the viewDelegate once this get’s set on us by the coordinator.
  • We use our viewModel reference to get all the formatted data we need, and to send any relevant events.
  • And finally, we implement the ViewDelegate protocol so the ViewModel can let us know when we have to update our screen.

Conclusion

That’s basically it. All the major parts of the architecture have been covered. The Scenes which own a storyboard and a Coordinator which instantiates ViewController’s with their respective ViewModel’s.

The next and last two parts of the series will focus on two other “extra” patterns that I think are really beneficial to the overall structure of the architecture.

Let’s start with ViewData’s since I already mentioned them in passing up above.

iOS Architecture: MVVM-C, ViewData’s (5/6)

--

--