MVVM: A Tutorial and Practical Example in Swift

MVVM rather than MVC? What are the differences, and why should we care? Here is an explanation, with a few diagrams (and an example) to help!

Image for post
Image for post
A representation of the MVVM model

MVVM was proposed by John Gossman in 2005. Interestingly the view should consist only of visual elements — and not make network calls or similar.

All architectures have advantages and disadvantages, but MVVM has become increasingly popular in implementations.

Some want a video, and here is one (it covers a slightly different example than the one in this article so they go well together!).

Prerequisites:

  • Swift’s Result type is used later in the post

Terminology

View Controller: Sits between the view and the model, tying them together (usually using the delegate pattern). The controller is not tightly bound to a concrete view, and communicates via a protocol to an abstraction. An example of this is the way that a UITableView communicates with its data source through the UITableViewDataSource protocol. Think of it as the how of the App. The primary job of the controller is to format the data from the model for the view to display.

Model: Where data, and logic that manipulates the data is stored. Perhaps model objects, or networking code is stored here.Think of this as the what of the App.

View: Present information to the user. Views are, well, UIViews and their subclasses. Think of it as the UI components that have to be controlled by the controller.

ViewModel: Contains fields that are to be displayed in the view.

Discussion

MVVM is considered suitable when you need to transform models into another representation for a view, and slims down view controllers that require several model-to-view transformations. MVVM improves the propensity of the code to be tested, particularly through unit testing.

However, MVVM can be tricky because it can be hard to design the ViewModel up front in order to maximise reusability and of course this means that we have more files to deal with.

Binding

Data bindings distinguish MVVM from MVC and MVP by binding fields within the view model to a view — this isn’t a concern of this particular article and it could even be said that this article is more of a recreation of MVP (Model-View-Presentor).

There are several options making this a MVVM implementation (and in this example we will look at just the first of these):

  • Use simple tools to create the bindings (in this case closures); and arguably this makes it wholly an MVP implementation
  • Use a third party library like RXSwift to bind the view to the viewmodel
  • The the Key-Value Observing pattern (KVO) to perform the binding

Components

  • Present the UI components
  • Bind UI components with the ViewModel

ViewModel

  • Deal with error handling and pagination
  • Provide interfaces to the view
  • Write presentational logic

Model

  • Business Data + Business Logic + Business rules

Implementation

View controller

  • Creates the viewModel (possibly with initial model data), and set up bindings (i.e. closures) so the view controller is informed of changes that take place in the viewModel

View model

  • Performs requests, and informs the view controller of changes
  • Should be UIKit independent
  • Typically formats data to be formatted for the view controller

Model

  • A typical data model

The most basic implementation

Image for post
Image for post
The simple implementation of MVVM shown here

The most basic implementation of MVVM is to display some static information in a view. To do this, we need to make sure that we set up the view, view controller, viewmodel and model correctly.

The code simply displays a piece of text in a label.

Image for post
Image for post
The output of this simple MVVM App

The simpleViewController:

This creates the view Model:

And subsequently the view:

The whole code sample is here: https://github.com/stevencurtis/SimpleMVVMMostBasic

The table implementation

So typically to get the UITableView to be populated with data I would use a simple store of the datatype and then (for example) use this in numberOfRowsInSection.

var data = [BreachModel]()

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

return data.count

}

However, once we have a ViewModel we can use this with the following:

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

return breachesViewModel.breaches.count

}

Image for post
Image for post
A sample display of breaches in a UITableview

The completed ViewModel looks like this:

The only slight confusion can come through the view, since the viewcontroller takes care of both the view and the model in this case (since the viewcontroller stores both the table and the calls (A simpler version with a plain View-ViewModel-ViewController-Model is ).

With the whole setup in the following repository: https://github.com/stevencurtis/SimpleMVVM

The networked implementation

  • make the model now is much larger (to match the API!) and conforms to codable
  • A HTTPManager has been coded that makes a request to an API, and delivers the resultant data through a closure
  • When the ViewModel has completed fetching from the API, it decodes the JSON and informs the ViewController through a closure

The main changes look like this:

Calling fetchBreaches from the view controller:

FetchBreaches in the ViewModel:

Which calls the new HTTPManager

With the full completed code in the following repo:

Conclusions

MVVM should make code easier to test and create, but is complicated by a lack of bindings in iOS which take away problems around providing single-responsibility components.

If you’d like a video version it’s right here: https://youtu.be/R7VmRTKPX3A

Want to get in contact? Try the link here:

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store