We don't have a clear, flexible solution for transitioning between screens. These are some thoughs of what we need.
For example, a username can appear on various screens. Tapping the username results in transtioning to the UserDetail screen ragardless of what the current screen.
// This should be possible from any RouteContext
this.router.push(.UserDetail, model: user)
It should be possible to transition to any route with any transtion style.
// These each show the same screen, with different transtions
this.router.push(.UserDetail, model: user)
this.router.present(.UserDetail, model: user)
this.router.transitionTo(.UserDetail, model: user, style: customTranstion)
A route should know when it's being entered/exited/shown/hidden.
protocol RouteContext {
func enter()
func exit()
func willShow()
func willHide()
}
class UserDetailRoute: RouteContext {
func enter() {
self.fetchInitialData()
}
func exit() {
this.cleanup()
}
func willShow() {
this.startAnimations()
}
func willHide() {
this.pauseAnimations()
}
}
// Routes.swift -- global routes, not scoped to router
enum Route {
case UserDetail
case FileInstanceDetail
case Login
// etc.
}
// Routable.swift
protocol Routable {
public func push(route: Route, model: AnyObject)
public func present(route: Route, model: AnyObject)
public func transitionTo(route: Route, model: AnyObject, style: TransitionDelegate)
}
// AppRouter.swift
class AppRouter {
let rootViewController = UINavigationController()
public func push(route: Route, model: AnyObject? = nil) {
let vc: UIViewController
switch route {
case .UserDetail:
if let user = model as User {
let context = UserDetailRoute(user: user)
vc = UserDetailViewController(context: context)
context.enter()
}
}
navigationController.pushViewController(vc, animated: true)
}
}
This seems a lot cleaner and more reusable than what we have now.
Just thinking out loud, but what if the RouteContext included a type alias for the model:
Then Router.push could be something like:
Not sure if that makes sense or not, and it makes 'model' a required param of
push
. Some routes might not need a model param, so maybe that doesn't really work…I like where you're going with this; I think we need to do something to make the router more flexible. I'll think some more and hopefully have more to say soon :)