Coordinators and memory management

Coordinators and memory management

A talk given at Cocoaheads Lille in April 2018.

F509c84c00a7a46a9404abfa90bf2a0d?s=128

Charles-Henri DUMALIN

April 19, 2018
Tweet

Transcript

  1. Coordinators and memory

  2. We all have this ViewController → Layout → View State

    management → Data fetching & persistance → Navigation
  3. Why is this? → ViewController have an unclear role in

    UIKit → Apple's vision of MVC is not matching our needs
  4. What is MVC?

  5. What are Apple's components of MVC?

  6. Why does this not match our expectations? → Apple expects

    us to do a local first app with CoreData → In this context their architecture makes perfect sense
  7. MVVM to the rescue

  8. MVVM to the rescue → The ViewController becomes just a

    part of the view level
  9. Remember our ViewController? → Layout: UIView → View State management:

    UIViewController → Data fetching & persistance: ViewModel → Navigation: ????
  10. None
  11. EXAMPLE CASE

  12. None
  13. Introducing Coordinator

  14. What does a Coordinator do? → Manages the navigation flow

    → Instanciates the controllers and injects dependencies
  15. How does it do it? → It's a plain Swift

    object → You do what you want with it → You just implement the Coordinator Protocol → You use delegation (or Reactive Programming) at the controller level
  16. Anatomy of a Coordinator public protocol Coordinator { func start(animated:

    Bool) }
  17. class AppCoordinator { let window: UIWindow let navigationController: UINavigationController! let

    homeController: HomeViewController! init(window: UIWindow) { self.window = window } } extension AppCoordinator: Coordinator { func start(animated: Bool) { homeController = HomeViewController.instanciateFromStoryboard() navigationController = UINavigationController(root: homeController) window.rootViewController = navigationController window.makeKeyAndVisible() } }
  18. class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? var coordinator:

    Coordinator! func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]? ) -> Bool { let window = UIWindow(frame: UIScreen.main.bounds) coordinator = AppCoordinator(window: window) coordinator.start(animated: false) self.window = window } }
  19. class DetailCoordinator { let navigationController: UINavigationController let detailController: DetailViewController init(_

    navigationController: UINavigationController) { self.navigationController = navigationController } } extension DetailCoordinator: Coordinator { func start(animated: Bool) { let detailController = DetailViewController.instanciateFromStoryboard() navigationController.pushViewController(detailController, animated: animated) } }
  20. class AppCoordinator { let window: UIWindow let navigationController: UINavigationController! let

    homeController: HomeViewController! var childCoordinator: Coordinator? init(window: UIWindow) { self.window = window } } extension AppCoordinator: Coordinator { func start(animated: Bool) { homeController = HomeViewController.instanciateFromStoryboard() homeController.delegate = self navigationController = UINavigationController(root: homeController) window.rootViewController = navigationController window.makeKeyAndVisible() } } extension AppCoordinator: HomeControllerDelegate { func didTouchDetailButton() { let coordinator = DetailCoordinator(_ navigationController: navigationController) coordinator.start() childCoordinator = coordinator } }
  21. Yay we did it!

  22. None
  23. Wait what?! Beware the zombie Coordinators and UIViewControllers

  24. None
  25. What's the problem here ? → UIKit creates a strong

    reference → But Coordinator should own it... → UIKit decides when the view is released
  26. Play fair with UIKit → Don't fight it, embrace it

    → UIKit will always be there
  27. None
  28. None
  29. None
  30. ! How do I let the parent Coordinator know that

    the Coordinator is not needed anymore?
  31. None
  32. The lifecycle probe → When the ViewController is deallocated it

    sends a message to the Coordinator → The Coordinator sends a message to its parent to be released
  33. SO MUCH WORK

  34. Meet Yui Github: CallMeSH/Yui

  35. Yui streamlines the process → Conform to the protocol →

    Follow the guidelines → You're done !
  36. DEMO Time

  37. Thank You Github: CallMeSH/Yui Twitter: @CallMeSH LinkedIn: Charles-Henri DUMALIN