Advertisement

Protocol-Oriented MVVM (extended edition)

Senior Software Engineer - iOS at Capital One
Nov. 10, 2015
Advertisement

More Related Content

Advertisement
Advertisement

Protocol-Oriented MVVM (extended edition)

  1. POMVVM@NATASHATHEROBOT
  2. "Swift Is a Protocol-Oriented Programming Language" — Dave Abrahams, Professor of Blowing-Your-Mind
  3. UITableViewDelegate UITableViewDataSource UITextFieldDelegate NSURLSessionDelegate CLLocationManagerDelegate MCSessionDelegate
  4. !
  5. !
  6. !
  7. !
  8. Artsy Engineering: MVVM in Swift
  9. MODEL let amount = 6729383.99
  10. VIEW Your balance is $6,729,383.99
  11. VIEWMODEL struct AccountViewModel { let displayBalance: String init(model: BankAccount) { let formattedBalance = model.balance.currencyValue displayBalance = "Your balance is (formattedBalance)" } }
  12. VIEWCONTROLLER var viewModel = ViewModel(model: Account)
  13. VIEWCONTROLLER var viewModel = ViewModel(model: Account)
  14. PROTOCOLS !!!
  15. THE PROBLEM class SwitchWithTextTableViewCell: UITableViewCell { func configure( title: String, titleFont: UIFont, titleColor: UIColor, switchOn: Bool, switchColor: UIColor = .purpleColor(), onSwitchToggleHandler: onSwitchToggleHandlerType? = nil) { // configure views here } }
  16. PROTOCOLS TO THE RESCUE !
  17. 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) }
  18. extension SwitchWithTextCellProtocol { var switchColor: UIColor { return .purpleColor() } }
  19. class SwitchWithTextTableViewCell: UITableViewCell { func configure(withDelegate delegate: SwitchWithTextCellProtocol) { // configure views here } }
  20. 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!") } } }
  21. CELLFORROWATINDEXPATH // YourViewController.swift let cell = tableView.dequeueReusableCellWithIdentifier("SwitchWithTextTableViewCell", forIndexPath: indexPath) as! SwitchWithTextTableViewCell // this is where the magic happens! cell.configure(withDelegate: MinionModeViewModel()) return cell
  22. !
  23. 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 } }
  24. // SwitchWithTextTableViewCell func configure(withDataSource dataSource: SwitchWithTextCellDataSource, delegate: SwitchWithTextCellDelegate?) { // configure views here }
  25. struct MinionModeViewModel: SwitchWithTextCellDataSource { var title = "Minion Mode!!!" var switchOn = true }
  26. 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!") } } }
  27. // SettingsViewController let viewModel = MinionModeViewModel() cell.configure(withDataSource: viewModel, delegate: viewModel) return cell
  28. !
  29. @MHOLLEMANS: MIXINS AND TRAITS IN SWIFT 2.0
  30. class AIPlayer: GameObject, AITrait, GunTrait, RenderTrait, HealthTrait { ... } class ZapMonster: GameObject, GunTrait, RenderTrait, HealthTrait, MovementTrait { ... }
  31. ! "
  32. 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) }
  33. protocol ImagePresentable { var imageName: String { get } } protocol TextFieldPresentable { var placeholder: String { get } var text: String { get } func onTextFieldDidEndEditing(textField: UITextField) }
  34. extension TextPresentable { var textColor: UIColor { return .blackColor() } var font: UIFont { return .systemFontOfSize(17) } }
  35. !!! class SwitchWithTextTableViewCell<T where T: TextPresentable, T: SwitchPresentable>: UITableViewCell { private var delegate: T? func configure(withDelegate delegate: T) { // configure views here } }
  36. extension MinionModeViewModel: TextPresentable { var text: String { return "Minion Mode" } var textColor: UIColor { return .blackColor() } var font: UIFont { return .systemFontOfSize(17.0) } }
  37. 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!") } } }
  38. let cell = tableView.dequeueReusableCellWithIdentifier("SwitchWithTextTableViewCell", forIndexPath: indexPath) as! SwitchWithTextTableViewCell<MinionModeViewModel> let viewModel = MinionModeViewModel() cell.configure(withDelegate: viewModel) return cell
  39. !"#
  40. "Change is the only constant." — Unknown
  41. class SwitchWithTextTableViewCell<T where T: TextPresentable, T: SwitchPresentable, T: ImagePresentable>: UITableViewCell { }
  42. extension MinionModeViewModel: ImagePresentable { var imageName: String { return "minionParty.png" } }
  43. !"
  44. > Use Protocols to Configure Your Views > Use Protocol Extensions for Defaults > Use ViewModels to Provide Data for the Protocols
  45. HOW CAN WE MAKE THIS BETTER?
Advertisement