MVVM in Swift
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 callsuper.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 aListingsViewModelType
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.