Upgrade to Pro — share decks privately, control downloads, hide ads and more …

A Story about Coordinators

A Story about Coordinators

One approach to reduce the amount of code in ViewControllers is the Coordinator. But what is a Coordinator and how should we use it? Amongst other things, we'll talk about how Coordinators help make ViewControllers more re-usable by separating out the flow of the application, and how it improves the testability of the app. We'll also talk about how we introduced Coordinators bit by bit into an existing application, challenges we ran into, and the benefits we've found.

Avatar for Ernesto Carrión

Ernesto Carrión

June 08, 2016

Other Decks in Programming

Transcript

  1. How it started > Massive View Controller > Viper /

    MVVM > Data Sources > Smarter Views > Presenters / ViewModels > Utilities / Helpers / Wrappers / Managers > Categories ❌
  2. The Problem > Rigid View Controllers > Coupled: > App

    Control flow > Data Mutation > Business Logic > Poor testing
  3. problems > App Flow Logic > Business Logic > Data

    Mutability > Counting on optional values
  4. func signInButtonPressed() { let email = getEmail() let password =

    getPassword() networkController.signin(email, password: password) { (user, error) in if let newUser = user { let rideViewController = RideViewController(user: newUser) self.navigationController?.setViewControllers([rideViewController], animated: true) } } }
  5. func signInButtonPressed() { let email = getEmail() let password =

    getPassword() ✅ networkController.signin(email, password: password) { (user, error) in if let newUser = user { let rideViewController = RideViewController(user: newUser) self.navigationController?.setViewControllers([rideViewController], animated: true) } } }
  6. func signInButtonPressed() { let email = getEmail() let password =

    getPassword() ✅ networkController.signin(email, password: password) { (user, error) in ⚠ if let newUser = user { let rideViewController = RideViewController(user: newUser) self.navigationController?.setViewControllers([rideViewController], animated: true) } } }
  7. func signInButtonPressed() { let email = getEmail() let password =

    getPassword() ✅ networkController.signin(email, password: password) { (user, error) in ⚠ if let newUser = user { let rideViewController = RideViewController(user: newUser) ❌ self.navigationController?.setViewControllers([rideViewController], animated: true) } } }
  8. func signInButtonPressed() { let email = getEmail() let password =

    getPassword() ✅ networkController.signin(email, password: password) { (user, error) in ⚠ if let newUser = user { let rideViewController = RideViewController(user: newUser) ❌ self.navigationController?.setViewControllers([rideViewController], animated: true) $ } } }
  9. Benefits > A place for our screen navigation logic >

    Immutable data in view controllers > Reuse View Controllers effectively > A/B Testing > Integration Tests > Smaller View Controllers
  10. LIMITS OF COORDINATORS > Small Application > Linear View Controller

    flow > Mutating too much data > Presenters / View Models
  11. protocol SignInViewControllerDelegate { func userWantsToSignIn(email: String, password: String) } protocol

    RideViewControllerDelegate { func userDidFinishWithRideController(controller: RideViewController) }
  12. class SignInViewController: UIViewController { func signInButtonPressed() { let email =

    getEmail() let password = getPassword() delegate?.userWantsToSignIn(email, password: password) } } class RideViewController: UIViewController { func afterSomethingHappens() { delegate?.userDidFinishWithRideController(self) } }
  13. class AppCoordinator : Coordinator, SignInViewControllerDelegate, RideViewControllerDelegate { let navigationController :

    UINavigationController // Parent VC let networkController : NetworkController var childCoordinators : [Coordinator] }
  14. class AppCoordinator : Coordinator { func start() { showAuthViewController() }

    func showAuthViewController() { let signInViewController = SignInViewController() signInViewController.delegate = self navigationController.viewControllers = [signInViewController] } }
  15. class AppCoordinator : Coordinator { func userWantsToSignIn(email: String, password: String)

    { networkController.signin(email, password: password) { (user, error) in if let newUser = user { self.showRideFlow(newUser) } } } func userDidFinishWithRideController(controller: RideViewController) { presentPaymentCoordinator() } }