Data-driven Screen Dispatching for iOS
The Coordinator Pattern is rather trendy at the moment. Soroush Khanlou and Paul Hudson have both written very fine blogposts about it, and I saw Paul talk about coordinators - briefly - at iOSDevUK in 2018. There are some great benefits from using Coordinators, but I can't help feeling it doesn't go far enough.
I propose that app navigation should be driven by data.
Data-driven navigation in a nutshell
My app doesn't want to show ViewControllers to the user; it wants to show data.
Architectural background for my apps
- I generally use a variation of MVVM, so user-interface state is held outside the ViewController
- this means my ViewControllers are always small and free of logic
Consequently, I really don't care about ViewControllers. I don't want to create them, I don't want to present them, I don't want to write code to wire them up.
Data-driven navigation example
In my Nearly Departed rewrite, I have a RouteModel
which defines a pair of rail stations:
struct RouteModel {
let fromStationCode: String
let toStationCode: String
}
My ViewModels will have a reference to a dispatcher object (more on that later), and will present a route like this:
let yorkToLeeds = RouteModel(fromStationCode: "YRK", toStationCode: "LDS")
dispatcher.dispatch(yorkToLeeds)
That's it. We're showing data to the user, not a ViewController.
The RouteModel
can be dispatched because of an extension which makes it conform to a Dispatchable
protocol - and it's that extension which decides how the data is shown to the user:
extension RouteModel: Dispatchable {
var dispatch: DispatchChange {
let viewModel = DeparturesViewModel(route: self)
return DispatchChange(presentation: .modal,
options: .embedInNavigationController,
viewModel: viewModel,
viewControllerType: DeparturesViewController.self)
}
}
Why?
There are several nice outcomes of this:
- my ViewModels can use a dispatcher to show data to the user; they don't care about how it's shown
- it's easily unit-testable; I can use SwiftMock to create a mock for the
Dispatching
protocol, and easily assert that the correct data is being presented - it still has the benefits of Soroush's coordinators - where ViewControllers are completely decoupled from each other
Source
There's an example implementation in this Gist.
First published 26 January 2019