Slide 1

Slide 1 text

App Architecture by Manual DI @yoshikuni_kato Tokyo iOS meetup 2018/07/21 1

Slide 2

Slide 2 text

Who am I ? • Yoshikuni KatoʢՃ౻༝܇ʣ • iOS Engineerʢ3.5 yearsʣ • Yahoo! Japan -> OHAKO -> Pangea • Twitter: @yoshikuni_kato • GitHub: @yoching • Interests: Software Design, FRP (ReactiveSwift), UI Implementation 2

Slide 3

Slide 3 text

Agenda 1. Coordinator Pattern 2. Goals 3. Architecture Sample 3

Slide 4

Slide 4 text

Coordinator Pattern 4

Slide 5

Slide 5 text

Connecting View Controllers 1 let nc = window?.rootViewController as! UINavigationController let episodesVC = nc.viewControllers[0] as! EpisodesViewController let storyboard = UIStoryboard(name: "Main", bundle: nil) episodesVC.didSelect = { episode in let detailVC = storyboard.instantiateViewControllerWithIdentifier("Detail") as! DetailViewController detailVC.episode = episode nc.pushViewController(detailVC, animated: true) } • transition logics are outside of view controller 1 https://talk.objc.io/episodes/S01E05-connecting-view-controllers 5

Slide 6

Slide 6 text

Coordinator Pattern 2 3 • Objects to handle view controller transition = Coordinator • View Controllers can be isolated each other -> DI friendly • Other names: Router (in VIPER), Wireframe, Navigation, ... 3 https://speakerdeck.com/yoching/coordinatorpatanfalseshi-jian 2 https://speakerdeck.com/yoching/hua-mian-qian-yi-falseguan-li-tomvvm 6

Slide 7

Slide 7 text

More commonized way // in ViewController enum EpisodesRoute { case detail(Episode) } protocol EpisodesRouting: class { var routeSelected: ((EpisodesRoute) -> Void)? { get set } } class EpisodesViewController: UIViewController, EpisodesRouting { var routeSelected: ((EpisodesRoute) -> Void)? } // in Coordinator episodesVC.routeSelected = { route in switch route { case .detail(let episode): // present detail } } (inspired by "Deep Linking at Kickstarter" @ SwiftTalk 4) 4 https://talk.objc.io/episodes/S01E49-deep-linking-at-kickstarter 7

Slide 8

Slide 8 text

8

Slide 9

Slide 9 text

Coordinator Pattern problems • 2 tasks in Coordinator • view transition • view controller creation • lots of dependencies 9

Slide 10

Slide 10 text

Goals 10

Slide 11

Slide 11 text

Goals • All dependencies are injected from outside ɹ • Coordinator doesn't do view controller creation ɹ • Project is well organized ɹ 11

Slide 12

Slide 12 text

Goals • All dependencies are injected from outside -> Manual DI 5 • Coordinator doesn't do view controller creation -> using ViewFactory, CoordinatorFactory • Project is well organized -> Application / UI / Component 6 6 Minimizing Decision Fatigue to Improve Team Productivity @ try! swift 2017, https://www.slideshare.net/DerekLee/ minimizing-decision-fatigue-to-improve-team-productivity 5 https://ja.wikipedia.org/wiki/%E4%BE%9D%E5%AD%98%E6%80%A7%E3%81%AE%E6%B3%A8%E5%85%A5 12

Slide 13

Slide 13 text

Architecture Sample 13

Slide 14

Slide 14 text

Sample Code • yoching/iOSAppArchitectureSample 7 7 https://github.com/yoching/iOSAppArchitectureSample 14

Slide 15

Slide 15 text

Figure 15

Slide 16

Slide 16 text

Development Workflow situation workflow make service make service -> update Components make view make VC & VM -> make function at ViewFactory make transition update Coordinator 16

Slide 17

Slide 17 text

More Practical Sample • yoching/JSONPlaceholderViewer 8 • persistance using CoreData • networking • ReactiveSwift 8 https://github.com/yoching/JSONPlaceholderViewer 17

Slide 18

Slide 18 text

Discussions • Over engineered? • Dependency management objects = DI container? 18

Slide 19

Slide 19 text

Thank you! @yoshikuni_kato 19