Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

201710 Fly Me to the View - iOS Conf SG

278 views

Published on

Navigation and Dependency Inversion are two key components of an advanced architecture. This talk is about separating the user events from the semantics, injecting dependencies, memory management, live within the Storyboards and without them. Make better applications following SOLID principles.

Published in: Software
  • Be the first to comment

201710 Fly Me to the View - iOS Conf SG

  1. 1. Fly Me to the View Jorge D. Ortiz-Fuentes @jdortiz
  2. 2. A Canonical Examples Production
  3. 3. #AdvArchMobile Agenda ★ Architecture & Responsibilities ★ A modular solution • Storyboards • XIBs only ★ Benefits ★ Recap
  4. 4. Persistance FW View Network LocationFW Presenter Entity Gateway Clean Architecture Interactor Entity
  5. 5. Where’s the beef? navigation
  6. 6. #AdvArchMobile Navigation ★ Events vs Semantics ★ Storyboard vs Decoupled VC ★ And without storyboards? ★ Dependency Injection ★ Memory Management
  7. 7. Responsibili ties
  8. 8. MVP
  9. 9. #AdvArchMobile View ★ Known by its beautiful face and its passivity ★ Receives the events and passes them to the presenter ★ Knows how to navigate
  10. 10. #AdvArchMobile Presenter ★ Provides meaning to the user events ★ Tells the view what to update ★ Knows when and where to navigate
  11. 11. #AdvArchMobile Connector ★ Knows the dependencies and how to connect them ★ Takes you to the next connector
  12. 12. What about MVVM?
  13. 13. #AdvArchMobile No worries ★ MVP Tells ★ MVVM Notifies ★ Feel free to embrace & extend
  14. 14. A modular solution
  15. 15. Decoupling
  16. 16. #AdvArchMobile View controller ★ Separate event from semantics ★ Still, navigation is done here
  17. 17. A new VC View (VC) Presenter Interactor Entity Gateway Connector View (VC) Presenter Interactor Entity Gateway Connector 1 23 4
  18. 18. Segue from VC
  19. 19. #AdvArchMobile View Controller: Events @IBAction func add(_ sender: UIBarButtonItem) { presenter.addButtonTapped() } override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { presenter.select(row: indexPath.row) }
  20. 20. #AdvArchMobile Presenter: Navigation Semantics func addButtonTapped() { view.navigateToAddProgrammer() } func select(row: Int) { if row < 0 !|| row !>= programmers.count { selectedId = nil } else { let programmer = programmers[row] selectedId = programmer.id view.navigateToProgrammerDetail() } }
  21. 21. #AdvArchMobile View Controller: Navigation func navigateToAddProgrammer() { performSegue(withIdentifier: SegueIdentifier.addProgrammer, sender: self) } func navigateToProgrammerDetail() { performSegue(withIdentifier: SegueIdentifier.showProgrammer, sender: self) }
  22. 22. #AdvArchMobile View Controller: Delegate DI override func prepare(for segue: UIStoryboardSegue, sender: Any?) { let identifier = try! segueIdentifier(for: segue) switch identifier { case .addProgrammer: connector.prepareAddProgrammer(viewController: segue.destination) case .showProgrammer: connector.prepareProgrammerDetail(viewController: segue.destination, presenter: presenter) } }
  23. 23. #AdvArchMobile Child Connector: Assemble func assembleModule(view: ProgrammerEditViewController) { let presenter = ProgrammerEditPresenter(otherDep: depencency) view.presenter = presenter view.connector = self presenter.view = view }
  24. 24. #MobAppArch Implementing navigation and back ★ Navigation destination is NOT decided by the view event ★ When presented modally, navigation back requires Unwind segue ★ In a navigation controller things happen naturally
  25. 25. Memory Management
  26. 26. Dismiss a VC View (VC) Presenter Interactor Entity Gateway Connector View (VC) Presenter Interactor Entity Gateway Connector 1 2
  27. 27. Passing parameters
  28. 28. #AdvArchMobile Having the Information ★ Perform segue & prepare for segue are disconnected ★ Information for injection: • Use sender: DON’T • State in View Controller • State in Presenter (preferred)
  29. 29. XIBs only
  30. 30. #AdvArchMobile Differences ★ Easier to pass the information ★ Easier to do the injection: Initializer instead of property ★ Presentation is done by the source ★ No “big picture” or unwind segues
  31. 31. #AdvArchMobile VC Injection via Initializer var presenter: ProgrammerEditPresenter init(presenter: ProgrammerEditPresenter, nibName: String? = nil, bundle: Bundle? = nil) { self.presenter = presenter super.init(nibName: nil, bundle: nil) presenter.view = self }
  32. 32. #AdvArchMobile Passing Information & Presentation func navigateToDetail(parameter: String) { let detailViewController = connector.prepareProgrammerDetail(paramete r: parameter) navigationController!?.pushViewController(d etailViewController, animated: true) }
  33. 33. Benefits
  34. 34. Modify Dependency Injection
  35. 35. #AdvArchMobile Dependencies Change ★ Create them in the connector ★ Pass them from one connector to the next
  36. 36. Testable
  37. 37. #AdvArchMobile Test Everything func testSegueToAddProgrammerInvokesConnectorToNavigate() { let connectorMock = ProgrammersListConnectorMock(some Dep: DepTestDummy()) sut.connector = connectorMock sut.performSegue(withIdentifier: ProgrammersTableViewControllerMock.SegueIdentifier.addProgr ammer, sender: sut) XCTAssertEqual(1, connectorMock.prepareAddProgrammerInvoked) }
  38. 38. A/B Testing
  39. 39. #AdvArchMobile Presenter func addButtonTapped() { if abSelector.isA { view.navigateToAddProgrammerA() } else { view.navigateToAddProgrammerB() } }
  40. 40. #AdvArchMobile Recap ★ Navigation is a key part of an advanced architecture: • Modular • Allows passive view • Not bound to implementation (storyboards) ★ Easy to implement & maintain ★ Clear benefits
  41. 41. – Anonymous iOS developer “Fly me to the View Let me play among the Apps”
  42. 42. Thank You!
  43. 43. 谢谢
  44. 44. Terima kasih!
  45. 45. ந"#
  46. 46. @jdortiz #AdvArchMobile

×