In a top secret project I am working on, I think I found a consistent way to create
UITableViewControllers in a reusable fashion without making a mess with massive view controllers.
The key ingredient is, as always, delegation from the view controller and thus composing larger components:
- … is a table view controller.
- … consumes
BananaViewModels on its
- … delegates displaying a huge header to
- … delegates cell display to
BananaViewControllerContents, which is data source and delegate to the table view.
- … responds to and delegates upward events from its contents.
The table view controller mostly delegates things away. It orchestrates the setup and keeps a strong reference to its components. It does’t change itself at all when new data is displayed, though.
This is huge, because you can now explicitly model view controller state changes as messages sent from the cells, for example.
The usual approach in contrast is to change the view controllers state upon interaction somehow. This will work in simple apps and with manual testing kind of fine, but it doesn’t scale well. Unit testing is very hard, too, because everything is so intertwined.
A better approach will utilize mutation of a model object instead which is the source of truth for the table view’s data source methods. The natural next step is to pry out that logic from the view controller, too, and then extract cell setup. Tests for these simple collaborators are short and highly focused.
The basic pattern is “copy & paste reusable.” If this works out well, I may even create abstractions, but I doubt this will be worth the effort for a while. Copy & paste works well enough for moving quickly at this early stage of development.
So that’s how data display flows really nicely down the tree of components. User interaction poses a different challenge: how are messages passed up the chain again? I’m experimenting with a few different approaches and will keep you posted once I settle for a particular solution.