View models in MVVM are responsible of making the model suitable for presenting by a view. Quite often model objects themselves have properties which can be directly presented by the view. SE-0195 added dynamic member lookup types. Using @dynamicMemberLookup we can add all the model object’s properties to the view model itself. Result, model.name is also accessible by calling name on the view model.
View model with @dynamicMemberLookup
Example app presents chemical element: symbol, name, atomic number, and atomic weight. Model object’s properties which can be displayed without transformations are symbol and name. Atomic number and weight are transformed and label is prepended to a value.

struct ChemicalElement {
let name: String // Hydrogen
let symbol: String // H
let atomicNumber: Int // 1
let atomicWeight: Double // 1.008
}
View model is initialised with an instance of chemical element. What we would like to have is accessing all the data by asking it from view model: viewModel.name, viewModel.symbol, viewModel.numberDescription, viewModel.weightDescription. Dynamic member lookup enables us adding all the model object’s properties to the view model with only some lines of code. It makes a real difference if the model and view model have a way more data than in the current example.
struct ContentView: View {
let viewModel: ContentViewModel
var body: some View {
VStack(spacing: 4) {
Text(viewModel.symbol).font(.system(size: 42)).fontWeight(.bold)
VStack(spacing: 4) {
Text(viewModel.name)
Group {
Text(viewModel.numberDescription)
Text(viewModel.weightDescription)
}.font(.footnote)
}
}
}
}
Let’s take a look on the view model. When view model is annotated with @dynamicMemerLookup, we’ll just need to implement one method. This is what is used to passing through model object’s data directly to the view. That is all we need to do for exposing model object’s properties on the view model level.
@dynamicMemberLookup
struct ContentViewModel {
private let chemicalElement: ChemicalElement
init(chemicalElement: ChemicalElement) {
self.chemicalElement = element
}
subscript<T>(dynamicMember keyPath: KeyPath<ChemicalElement, T>) -> T {
return chemicalElement[keyPath: keyPath]
}
var numberDescription: String {
return "Number: \(chemicalElement.atomicNumber)"
}
var weightDescription: String {
return "Weight: \(chemicalElement.atomicWeight)"
}
}
Summary
Dynamic member lookup in Swift is useful addition to MVVM pattern when there is need to expose model’s properties directly to the view. When working with models with many properties, it is very useful.
Please also take a look on MVVM in SwiftUI.
If this was helpful, please let me know on Mastodon@toomasvahter or Twitter @toomasvahter. Feel free to subscribe to RSS feed. Thank you for reading.