I don’t know if autoconfigurable can be found in the dictionary, but I’m going to use it anyway because it best describes what we’re going to do in this chapter. In the previous chapter, we refactored the SettingsViewController
class. In the tableView(_:cellForRowAt:)
method, we create an instance of type SettingsRepresentable?
. The view controller manually configures each table view cell, using a view model. But why can’t the table view cell take care of its own configuration?
All the table view cell needs to do is ask the view model for the values it needs and populate itself with data. This is very different from handing a model to a view, which certainly isn’t what we intend to do. The table view cell won’t know about the model, it will simply use the interface of the view model we give it.
To make this work, we need to make some changes to the SettingsTableViewCell
class. Open SettingsTableViewCell.swift and define a method named configure(withViewModel:)
. The method accepts one argument of type SettingsRepresentable
. In the body of the method, we set the text
property of the mainLabel
outlet and we update the accessoryType
property of the table view cell.
SettingsTableViewCell.swift
All that’s left for us to do is updating the SettingsViewController
class. Open SettingsViewController.swift and navigate to the tableView(_:cellForRowAt:)
method. The view controller no longer needs to configure the table view cell. Instead, we invoke the configure(withViewModel:)
method of the table view cell and pass in the view model. I’m sure you agree that this looks quite nice.
SettingsViewController.swift
Notice that the view controller is still involved, but its role is very limited. By implementing the configure(withViewModel:)
method and handing a view model to the table view cell, we’ve slightly deviated from the Model-View-ViewModel pattern we discussed in the introduction of this book.
But that’s fine. Views need to be dumb. They shouldn’t know what they’re displaying. That still applies to the SettingsTableViewCell
class. The table view cell only uses the interface of the view model to configure itself.
I want to highlight the role of the SettingsRepresentable
protocol in the story. The SettingsRepresentable
protocol serves two purposes. The most obvious task of the SettingsRepresentable
protocol is defining an interface. Because the view models we defined earlier conform to this protocol, the SettingsTableViewCell
class only needs to have the ability to handle an object of type SettingsRepresentable
.
But the SettingsRepresentable
protocol performs a more important but less obvious task. It adds a layer of abstraction. The SettingsRepresentable
protocol ensures that the SettingsTableViewCell
class doesn’t need to know about the view models we defined (SettingsViewTimeViewModel
, SettingsViewUnitsViewModel
, and SettingsViewTemperatureViewModel
). That’s an important advantage and that’s the beauty and elegance of protocol-oriented programming.
The settings view controller is a simple view controller, but I hope you can see the potential of the Model-View-ViewModel pattern in simplifying view controllers. The settings view controller is very focused. All it does is manage its view and subviews and handle user interaction. That’s the primary role of every view controller, and this applies to MVVM as well as MVC.
In the next chapter, we apply what we’ve learned in the past two chapter to the week view controller.