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

Protocol-Oriented MVVM

Protocol-Oriented MVVM

With Swift 2.0 came Protocol Extensions, which make Swift a Protocol-Oriented Programming Language. Learn what that means and how to apply protocol extensions to create beautiful and robust code without ever defaulting to subclassing.

By Natasha the Robot http://natashatherobot.com

Powered by http://xebia.com

B94d88549eaca9755b9346a0383b41bb?s=128

do{iOS} conference

November 09, 2015
Tweet

Transcript

  1. POMVVM @NATASHATHEROBOT

  2. None
  3. None
  4. "Swift Is a Protocol-Oriented Programming Language" — Dave Abrahams, Professor

    of Blowing-Your-Mind
  5. UITableViewDelegate UITableViewDataSource UITextFieldDelegate NSURLSessionDelegate CLLocationManagerDelegate MCSessionDelegate

  6. !

  7. !

  8. !

  9. !

  10. Artsy Engineering: MVVM in Swift

  11. MODEL let amount = 6729383.99

  12. VIEW Your balance is $6,729,383.99

  13. VIEWMODEL struct AccountViewModel { let displayBalance: String init(model: BankAccount) {

    let formattedBalance = model.balance.currencyValue displayBalance = "Your balance is \(formattedBalance)" } }
  14. VIEWCONTROLLER var viewModel = ViewModel(model: Account)

  15. None
  16. None
  17. None
  18. VIEWCONTROLLER var viewModel = ViewModel(model: Account)

  19. PROTOCOLS !!!

  20. None
  21. THE PROBLEM class SwitchWithTextTableViewCell: UITableViewCell { func configure( title: String,

    titleFont: UIFont, titleColor: UIColor, switchOn: Bool, switchColor: UIColor = .purpleColor(), onSwitchToggleHandler: onSwitchToggleHandlerType? = nil) { // configure views here } }
  22. PROTOCOLS TO THE RESCUE !

  23. protocol SwitchWithTextCellProtocol { var title: String { get } var

    titleFont: UIFont { get } var titleColor: UIColor { get } var switchOn: Bool { get } var switchColor: UIColor { get } func onSwitchTogleOn(on: Bool) }
  24. extension SwitchWithTextCellProtocol { var switchColor: UIColor { return .purpleColor() }

    }
  25. class SwitchWithTextTableViewCell: UITableViewCell { func configure(withDelegate delegate: SwitchWithTextCellProtocol) { //

    configure views here } }
  26. struct MinionModeViewModel: SwitchWithTextCellProtocol { var title = "Minion Mode!!!" var

    switchOn = true var switchColor: UIColor { return .yellowColor() } func onSwitchTogleOn(on: Bool) { if on { print("The Minions are here to stay!") } else { print("The Minions went out to play!") } } }
  27. CELLFORROWATINDEXPATH // YourViewController.swift let cell = tableView.dequeueReusableCellWithIdentifier("SwitchWithTextTableViewCell", forIndexPath: indexPath) as!

    SwitchWithTextTableViewCell // this is where the magic happens! cell.configure(withDelegate: MinionModeViewModel()) return cell
  28. !

  29. protocol SwitchWithTextCellDataSource { var title: String { get } var

    switchOn: Bool { get } } protocol SwitchWithTextCellDelegate { func onSwitchTogleOn(on: Bool) var switchColor: UIColor { get } var textColor: UIColor { get } var font: UIFont { get } }
  30. // SwitchWithTextTableViewCell func configure(withDataSource dataSource: SwitchWithTextCellDataSource, delegate: SwitchWithTextCellDelegate?) { //

    configure views here }
  31. struct MinionModeViewModel: SwitchWithTextCellDataSource { var title = "Minion Mode!!!" var

    switchOn = true }
  32. extension MinionModeViewModel: SwitchWithTextCellDelegate { var switchColor: UIColor { return .yellowColor()

    } func onSwitchTogleOn(on: Bool) { if on { print("The Minions are here to stay!") } else { print("The Minions went out to play!") } } }
  33. // SettingsViewController let viewModel = MinionModeViewModel() cell.configure(withDataSource: viewModel, delegate: viewModel)

    return cell
  34. !

  35. @MHOLLEMANS: MIXINS AND TRAITS IN SWIFT 2.0

  36. None
  37. None
  38. class AIPlayer: GameObject, AITrait, GunTrait, RenderTrait, HealthTrait { ... }

    class ZapMonster: GameObject, GunTrait, RenderTrait, HealthTrait, MovementTrait { ... }
  39. ! "

  40. protocol TextPresentable { var text: String { get } var

    textColor: UIColor { get } var font: UIFont { get } } protocol SwitchPresentable { var switchOn: Bool { get } var switchColor: UIColor { get } func onSwitchTogleOn(on: Bool) }
  41. protocol ImagePresentable { var imageName: String { get } }

    protocol TextFieldPresentable { var placeholder: String { get } var text: String { get } func onTextFieldDidEndEditing(textField: UITextField) }
  42. extension TextPresentable { var textColor: UIColor { return .blackColor() }

    var font: UIFont { return .systemFontOfSize(17) } }
  43. !!! class SwitchWithTextTableViewCell<T where T: TextPresentable, T: SwitchPresentable>: UITableViewCell {

    private var delegate: T? func configure(withDelegate delegate: T) { // configure views here } }
  44. extension MinionModeViewModel: TextPresentable { var text: String { return "Minion

    Mode" } var textColor: UIColor { return .blackColor() } var font: UIFont { return .systemFontOfSize(17.0) } }
  45. extension MinionModeViewModel: SwitchPresentable { var switchOn: Bool { return false

    } var switchColor: UIColor { return .yellowColor() } func onSwitchTogleOn(on: Bool) { if on { print("The Minions are here to stay!") } else { print("The Minions went out to play!") } } }
  46. let cell = tableView.dequeueReusableCellWithIdentifier("SwitchWithTextTableViewCell", forIndexPath: indexPath) as! SwitchWithTextTableViewCell<MinionModeViewModel> let viewModel

    = MinionModeViewModel() cell.configure(withDelegate: viewModel) return cell
  47. !"#

  48. "Change is the only constant." — Unknown

  49. None
  50. class SwitchWithTextTableViewCell<T where T: TextPresentable, T: SwitchPresentable, T: ImagePresentable>: UITableViewCell

    { }
  51. extension MinionModeViewModel: ImagePresentable { var imageName: String { return "minionParty.png"

    } }
  52. !"

  53. > Use Protocols to Configure Your Views > Use Protocol

    Extensions for Defaults > Use ViewModels to Provide Data for the Protocols
  54. HOW CAN WE MAKE THIS BETTER?