Thursday, October 22, 2015

MVVM in Swift

Ash Furrow:

View models don’t have any access to the user interface. You should not even import UIKit in a view model. Typically, a view controller observes the view model somehow to know when there’s new data to display. This can be done through KVO or FRP.


My solution was to put the enum in the view model, and have the view model expose a signal defining which of the two layouts should be used. Based on the selected segment index, the view model decides which layout should be used and sends that value on a signal. The view controller is responsible for mapping that signal into a configured layout, then setting that layout on the collection view.


Defining these signals on a view model can be tricky. Swift initializers have strict rules around when properties are assigned. The signals need access to the internal state of the view model, so they need to be created after calling super.init(). However, we can’t call super.init() until all our properties have been assigned to, including the signal properties.


While writing tests, I found it difficult to subclass the existing view model (for stubbing purposes). Since the view model’s initializer has side-effects (starting recurring network requests), I can’t call super.init(). Instead, I made a ListingsViewModelType protocol. The view controller only interacts with the view model through this protocol – it has no reference to the class itself. Now creating a stubbed view model is as easy as conforming to a protocol.

Comments RSS · Twitter

Leave a Comment