Save 37% off PRO during our Black Friday Sale! »

Introduction of coordinator pattern

D46e420ca5a57819d1d93d9fb10b9905?s=47 ysk-tngc
February 16, 2018

Introduction of coordinator pattern

D46e420ca5a57819d1d93d9fb10b9905?s=128

ysk-tngc

February 16, 2018
Tweet

Transcript

  1. $PPSEJOBUPS1BUUFSOͷ঺հ

  2. ઃܭύλʔϯ৭ʑ

  3. ઃܭύλʔϯ৭ʑ .PEFM7JFX$POUSPMMFS .PEFM7JFX1SFTFOUFS .PEFM7JFX7JFX.PEFM $MFBO"SDIJUFDUVSF %PNBJO%SJWFO%FTJHO

  4. ઃܭύλʔϯ৭ʑ .PEFM7JFX$POUSPMMFS .PEFM7JFX1SFTFOUFS .PEFM7JFX7JFX.PEFM $MFBO"SDIJUFDUVSF %PNBJO%SJWFO%FTJHO େࡶ೺ʹݴ͏ͱɺJ04 "OESPJE։ൃͰ͸ʜ 7JFXͱʮͦΕҎ֎ʯʹ෼͚ͯɺ ʮͦΕҎ֎ʯΛͲ͏ઃܭ͢Δ͔

  5. .7̋̋ͷ̋̋͸୭͕؅ཧ͢Δͷ͔໰୊

  6. .7̋̋ͷ̋̋͸୭͕؅ཧ͢Δͷ͔໰୊ final class CurrentViewController: UIViewController { // 1. ΠϕϯτΛड͚औΔ @IBAction

    func nextButtonTapped(_ sender: UIButton) { // 2. ࣍ͷը໘Λੜ੒ let nextVC = UIStoryboard(name: "Next", bundle: nil) .instantiateInitialViewController() as! NextViewController // 3. ࣍ͷը໘ʹඞཁͳ ViewModel Λੜ੒ nextVC.viewModel = NextViewModel() // 4. ը໘ભҠ self.navigationController?.pushViewController(nextVC, animated: true) } }
  7. .7̋̋ͷ̋̋͸୭͕؅ཧ͢Δͷ͔໰୊ final class CurrentViewController: UIViewController { // 1. ΠϕϯτΛड͚औΔ @IBAction

    func nextButtonTapped(_ sender: UIButton) { // 2. ࣍ͷը໘Λੜ੒ let nextVC = UIStoryboard(name: "Next", bundle: nil) .instantiateInitialViewController() as! NextViewController // 3. ࣍ͷը໘ʹඞཁͳ ViewModel Λੜ੒ nextVC.viewModel = NextViewModel() // 4. ը໘ભҠ self.navigationController?.pushViewController(nextVC, animated: true) } } Ҏ֎͸7JFXͷ࢓ࣄͰ͸ͳ͍ͷͰ͸ʁ
  8. $PPSEJOBUPS1BUUFSO

  9. $PPSEJOBUPS1BUUFSO ը໘ભҠॲཧΛߦ͏$PPSEJOBUPSΫϥε 7JFX$POUSPMMFS͸  ͷॲཧΛ $PPSEJOBUPSʹσϦήʔτ

  10. class Coordinator { // ਌ Coordinator private(set) weak var parentCoodinator:

    Coordinator? // ࢠ Coordinator private(set) var childCoordinators: [Coordinator] = [] /// Coordinator Λελʔτ (ը໘ભҠॲཧ) /// ࢠΫϥεͰඞͣ override ͢Δ func start() { fatalError("This method must be overrided.") } /// Coordinator Λऴྃ func finish() { removeFromParentCoodinator() } /// ࣍ͷ Coordinator Λ childCoordinators ʹ֨ೲ /// /// - Parameter childCoordinator: ࣍ͷ Coordinator func addChildCoordinator(_ childCoordinator: Coordinator) { childCoordinators.append(childCoordinator) childCoordinator.parentCoodinator = self } /// ࣗ਎Λ਌͔Β࡟আ͢Δ private func removeFromParentCoodinator() { guard let parent = parentCoodinator else { return } for (index, element) in parent.childCoordinators.enumerated() { if element === self { parent.childCoordinators.remove(at: index) break } } } }
  11. αϯϓϧΞϓϦ

  12. 'JSTU7JFX$POUSPMMFSTXJGU protocol FirstViewControllerDelegate: class { func firstViewController(_ firstViewController: FirstViewController, didTap

    action: FirstViewController.Action) } final class FirstViewController: UIViewController { enum Action { case next } var viewModel: FirstViewModel! weak var delegate: FirstViewControllerDelegate? @IBAction func nextButtonTapped(_ sender: UIButton) { delegate?.firstViewController(self, didTap: .next) } }
  13. 'JSTU$PPSEJOBUPSTXJGU final class FirstCoordinator: Coordinator { private let navigationController: UINavigationController

    init(navigationController: UINavigationController) { self.navigationController = navigationController } override func start() { let vc = UIStoryboard(name: "First", bundle: nil) .instantiateInitialViewController() as! FirstViewController vc.delegate = self navigationController.setViewControllers([vc], animated: false) } } extension FirstCoordinator: FirstViewControllerDelegate { func firstViewController(_ firstViewController: FirstViewController, didTap action: FirstViewController.Action) { switch action { case .next: let nextCoordinator = SecondCoordinator(parentViewController: navigationController) addChildCoordinator(nextCoordinator) nextCoordinator.start() } } }
  14. @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? private

    var firstCoordinator: FirstCoordinator! func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { // ͍ͭ΋Ͳ͓Γ Window ͱ RootViewController Λ༻ҙ͢Δ let window = UIWindow(frame: UIScreen.main.bounds) let rootNavigationController = UINavigationController() window.rootViewController = rootNavigationController window.makeKeyAndVisible() // ࠷ॳͷ Coordinator Λ start let firstCoordinator = FirstCoordinator(navigationController: rootNavigationController) firstCoordinator.start() self.firstCoordinator = firstCoordinator self.window = window return true } } "QQ%FMFHBUFTXJGU
  15. 'JSTU$PPSEJOBUPSTXJGU final class FirstCoordinator: Coordinator { private let navigationController: UINavigationController

    init(navigationController: UINavigationController) { self.navigationController = navigationController } override func start() { let vc = UIStoryboard(name: "First", bundle: nil) .instantiateInitialViewController() as! FirstViewController vc.delegate = self navigationController.setViewControllers([vc], animated: false) } } extension FirstCoordinator: FirstViewControllerDelegate { func firstViewController(_ firstViewController: FirstViewController, didTap action: FirstViewController.Action) { switch action { case .next: let nextCoordinator = SecondCoordinator(parentViewController: navigationController) addChildCoordinator(nextCoordinator) nextCoordinator.start() } } }
  16. 'JSTU$PPSEJOBUPSTXJGU final class FirstCoordinator: Coordinator { private let navigationController: UINavigationController

    init(navigationController: UINavigationController) { self.navigationController = navigationController } override func start() { let vc = UIStoryboard(name: "First", bundle: nil) .instantiateInitialViewController() as! FirstViewController vc.delegate = self navigationController.setViewControllers([vc], animated: false) } } extension FirstCoordinator: FirstViewControllerDelegate { func firstViewController(_ firstViewController: FirstViewController, didTap action: FirstViewController.Action) { switch action { case .next: let nextCoordinator = SecondCoordinator(parentViewController: navigationController) addChildCoordinator(nextCoordinator) nextCoordinator.start() } } }
  17. final class SecondCoordinator: Coordinator { private let parentViewController: UIViewController private

    var navigationController: UINavigationController! init(parentViewController: UIViewController) { self.parentViewController = parentViewController } override func start() { let vc = UIStoryboard(name: "Second", bundle: nil) .instantiateInitialViewController() as! SecondViewController vc.delegate = self let navigationVC = UINavigationController(rootViewController: vc) parentViewController.present(navigationVC, animated: true, completion: nil) self.navigationController = navigationVC } } extension SecondCoordinator: SecondViewControllerDelegate { func secondViewController(_ secondViewController: SecondViewController, didTap action: SecondViewController.Action) { switch action { case .close: self.navigationController.dismiss(animated: true, completion: { [weak self] in self?.finish() }) } } } 4FDPOE$PPSEJOBUPSTXJGU
  18. protocol SecondViewControllerDelegate: class { func secondViewController(_ secondViewController: SecondViewController, didTap action:

    SecondViewController.Action) } final class SecondViewController: UIViewController { enum Action { case close } var viewModel: SecondViewModel! weak var delegate: SecondViewControllerDelegate? override func viewDidLoad() { super.viewDidLoad() navigationItem.leftBarButtonItem = UIBarButtonItem(title: "ด͡Δ", style: .done, target: self, action: #selector(closeButtonTapped(_:))) } @objc private func closeButtonTapped(_ sender: UIBarButtonItem) { delegate?.secondViewController(self, didTap: .close) } } 4FDPOE7JFX$POUSPMMFSTXJGU
  19. final class SecondCoordinator: Coordinator { private let parentViewController: UIViewController private

    var navigationController: UINavigationController! init(parentViewController: UIViewController) { self.parentViewController = parentViewController } override func start() { let vc = UIStoryboard(name: "Second", bundle: nil) .instantiateInitialViewController() as! SecondViewController vc.delegate = self let navigationVC = UINavigationController(rootViewController: vc) parentViewController.present(navigationVC, animated: true, completion: nil) self.navigationController = navigationVC } } extension SecondCoordinator: SecondViewControllerDelegate { func secondViewController(_ secondViewController: SecondViewController, didTap action: SecondViewController.Action) { switch action { case .close: self.navigationController.dismiss(animated: true, completion: { [weak self] in self?.finish() }) } } } 4FDPOE$PPSEJOBUPSTXJGU
  20. ิ଍ͳͲ $PPSEJOBUPS͸/BWJHBUJPO$POUSPMMFS΍ 5BC#BS$POUSPMMFSͷ୯ҐͰ࡞Δ ϝϦοτɾσϝϦοτ 7JFX$POUSPMMFSͷίʔυΛγϯϓϧʹͰ͖Δ શମͷίʔυྔ͕ଟ͘ͳΓ͕ͪ

  21. ࢀߟจݙ IUUQLIBOMPVDPNDPPSEJOBUPSTSFEVY IUUQTHJUIVCDPN"OESFZ1BOPW"QQMJDBUJPO$PPSEJOBUPS αϯϓϧίʔυ IUUQTHJUIVCDPNZTLUOHD4JNQMF$PPSEJOBUPS1BUUFSO