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

Data driven view controllers

Data driven view controllers

Originally posted here: https://speakerdeck.com/vmalakhovskiy/data-driven-view-controllers

Github link: https://github.com/vmalakhovskiy/data-driven-vc

Vitaly about his workshop:
"I will show how to unify/simplify view-presenter communication, using data-driven approauch. Of cource a bit about functional programming, code generation, comparison with other architectures and more."

This workshop was made for CocoaHeads Kyiv #14 which took place Oct 6 2018.

Db84cf61fdada06b63f43f310b68b462?s=128

CocoaHeads Ukraine

October 06, 2018
Tweet

More Decks by CocoaHeads Ukraine

Other Decks in Programming

Transcript

  1. data-driven view controllers Vitalii Malakhovskyi Vitalii Malakhovskyi, BetterMe 1

  2. Vitalii Malakhovskyi, BetterMe 2

  3. Plan » what is data driven view controllers? » basic

    examples » code » home work: github Vitalii Malakhovskyi, BetterMe 3
  4. what is that, data-driven view controllers? Vitalii Malakhovskyi, BetterMe 4

  5. simplest view data representation as possible Vitalii Malakhovskyi, BetterMe 5

  6. struct/enum immutable! Vitalii Malakhovskyi, BetterMe 6

  7. struct ViewData { let title: String let message: String }

    Vitalii Malakhovskyi, BetterMe 7
  8. Doesn't know about » entities » managed objects » models

    » services » etc Vitalii Malakhovskyi, BetterMe 8
  9. it's only about view Vitalii Malakhovskyi, BetterMe 9

  10. May contain: » string, number, bool » struct, enum, array

    » nested » closure <- for output Vitalii Malakhovskyi, BetterMe 10
  11. ()->() Vitalii Malakhovskyi, BetterMe 11

  12. (Input)->() Vitalii Malakhovskyi, BetterMe 12

  13. ((Input)->())? Vitalii Malakhovskyi, BetterMe 13

  14. (Input)->(Output) Vitalii Malakhovskyi, BetterMe 14

  15. (Input)-> throws () Vitalii Malakhovskyi, BetterMe 15

  16. struct Props { let title: String let journeys: [ViewData.Journey] struct

    Journey { let name: String let description: String let image: UIImage let progress: String let isLocked: Bool let onSelect: () -> () } } Vitalii Malakhovskyi, BetterMe 16
  17. struct Props { let title: String let journeys: [ViewData.Journey] struct

    Journey { let name: String let description: String let image: UIImage let progress: String let isLocked: Bool let onSelect: () -> () } } Vitalii Malakhovskyi, BetterMe 17
  18. unidirectional Vitalii Malakhovskyi, BetterMe 18

  19. once somthing changed everything gets updated Vitalii Malakhovskyi, BetterMe 19

  20. main idea only valid state Vitalii Malakhovskyi, BetterMe 20

  21. wrong struct Interface { let programs: [Program] let temperatures: [Temperature]

    let RPMs: [RPM] enum Program {} enum Temperature {} enum RPM {} } Vitalii Malakhovskyi, BetterMe 21
  22. correct enum Interface { case handWash90Degree case wool30Degree case off

    } Vitalii Malakhovskyi, BetterMe 22
  23. Vitalii Malakhovskyi, BetterMe 23

  24. enum Props { case loading([Loading]) case error(title: String, message: String,

    onReload: () -> ()) case data([Data]) struct Data {} struct Loading {} } Vitalii Malakhovskyi, BetterMe 24
  25. should not relay on previous data Vitalii Malakhovskyi, BetterMe 25

  26. single source of update Vitalii Malakhovskyi, BetterMe 26

  27. UIView/UIViewController Vitalii Malakhovskyi, BetterMe 27

  28. func render(props: Props) { self.props = props view.setNeedsLayout() } func

    viewWillLayoutSubviews() { super.viewWillLayoutSubviews() /// redraw view state } Vitalii Malakhovskyi, BetterMe 28
  29. EXAMPLE Vitalii Malakhovskyi, BetterMe 29

  30. 1 Vitalii Malakhovskyi, BetterMe 30

  31. Presenter <- View Vitalii Malakhovskyi, BetterMe 31

  32. ViewData should be observable Vitalii Malakhovskyi, BetterMe 32

  33. protocol ViewModel { var viewData: Property<ViewData> { get } }

    Vitalii Malakhovskyi, BetterMe 33
  34. class ViewController: UIViewController { func viewDidLoad() { viewModel.viewData.producer.startWithValues { _

    in view.setNeedsLayout() } } func viewWillLayoutSubviews() { switch viewModel.viewData.value { ... } } } Vitalii Malakhovskyi, BetterMe 34
  35. how to achieve this? » reactive cocoa » rxswift »

    handmade observations » KVO Vitalii Malakhovskyi, BetterMe 35
  36. 2 Vitalii Malakhovskyi, BetterMe 36

  37. Presenter <-> View Vitalii Malakhovskyi, BetterMe 37

  38. VIPER Vitalii Malakhovskyi, BetterMe 38

  39. /// View -> Presenter protocol ViewOutput { func viewIsReady() }

    /// Presenter -> View protocol PresenterOutput: { func receiveUpdate(with data: ViewData) } Vitalii Malakhovskyi, BetterMe 39
  40. space for bugs Vitalii Malakhovskyi, BetterMe 40

  41. 3 Vitalii Malakhovskyi, BetterMe 41

  42. Presenter -> View Vitalii Malakhovskyi, BetterMe 42

  43. class ViewController: UIViewController { struct ViewData {} func render(viewData: ViewData)

    { self.viewData = viewData view.setNeedsLayout() } } struct Presenter { let render: (ViewData) -> () func handleNewAppState(...) // calls render } Vitalii Malakhovskyi, BetterMe 43
  44. View has no dependencies Vitalii Malakhovskyi, BetterMe 44

  45. UIKit owns UIViewController store owns presenter Vitalii Malakhovskyi, BetterMe 45

  46. CODE! Vitalii Malakhovskyi, BetterMe 46

  47. * simple input * input + validation * multistate screen

    * animation * MVVM vc DD MVVM * VIPER vc DD VIPER * MVC vc DD MVC Vitalii Malakhovskyi, BetterMe 47
  48. GITHUB github.com/vmalakhovskiy/data-driven-vc Vitalii Malakhovskyi, BetterMe 48

  49. THANKS! Vitalii Malakhovskyi, BetterMe 49

  50. * Data-Driven View Controllers. Tips and Tricks * github *

    Redux Vitalii Malakhovskyi, BetterMe 50
  51. Questions? Vitalii Malakhovskyi, BetterMe 51

  52. purpleshirted Vitalii Malakhovskyi VitaliyMal vmalakhovskiy Vitalii Malakhovskyi, BetterMe 52