Model–View–View Model (MVVM)
MVVM is a structural pattern that focuses on three pieces:
-
Model: In the most practical sense, any data to bring on screen. Could be mutable by the user, or static. (Similar to MVC).
-
View: In the strictest sense, the
NSView
orUIView
subclass, orSwiftUI.View
component that draws pixels on screen to somehow visualize the model. (Similar to MVC). -
View Model: A representation of the Model that’s designed to cooperate with the View. In SwiftUI, Combine, RxSwift, this is often reactive, driving the UI with live changes.
View Model as Data Transfer Object
The View Model can be a dumb data-transfer object (DTO) that is coupled to the view: when you need to display a person’s age in a text field, you declare age: String
to match the text field’s expectation.
This is an important change already and removes a big burden from the Controller: By assembling a special model for consumption by the view, you isolate points for change. You only need to change 1 place where the “true Model” becomes the “View Model”. This decouples the View from the Model through a layer of abstraction.
The View doesn’t need to know the Model, and it cannot even by accident change database entities, and the Model doesn’t need to worry about being displayable.
Assembly of this View Model could be done by a Presenter, a term also used in the VIPER architectural pattern.
Reactive View Models and Cocoa Bindings
The View Model can also be a two-way live view into the app’s overall state, and even some persistence mechanism like a database or cloud storage. The View Model then exposes reactive bindings like @Published
properties instead of the usual.
Interestingly, reactive bindings in View Models echo Key–Value Coding (KVC) and Key–Value Observation (KVO) that was possible in Objective-C, and still is if you use dynamic dispatch via @objc
. Only KVO was brittle and required runtime checks since it came with no compile time guarantees.
In the extreme case, a mutable reactive View Model is just the modern equivalent of a Core Data NSManagedObject
with (macOS exclusive) Cocoa Bindings of UI components directly into the data store. With all its downsides.
Posts on the topic
Aug 3 2023 |
SwiftUI.View Is Your ViewModel Hypothesis: You already have a View Model when you work with SwiftUI, which is the View type itself. |
Jan 5 2020 |
Maybe Call Your UI Configurion Objects ViewData Instead of ViewModel Getting out of the MVVM mindset helps see the connection between UI and UI-specific state that you derive from your model. |
Mar 7 2019 |
Do Not Apply Code Heuristics When You Need a Broader Perspective |
Jun 16 2018 | |
Jun 6 2018 | |
Jan 26 2017 | |
Jan 11 2017 | |
Oct 8 2016 | |
Aug 9 2016 | |
Jul 21 2016 | |
Jul 18 2016 |
I'll Split Up the Monolithic View Model in TableFlip. Here's What I Expect to Happen |
Mar 25 2016 |
5 Heuristics for "I have a complicated nested view controller setup. How do I handle passing data?" |
Jan 16 2016 | |
Dec 19 2015 |
Separate Read Model from Write Model to Support Complex Forms |
Dec 14 2015 | |
Nov 25 2015 | |
Oct 16 2015 | |
Oct 14 2015 | |
Jun 19 2015 | |
Jan 23 2015 | |
Dec 19 2014 |