Guest User

Untitled

a guest
Jan 17th, 2019
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.19 KB | None | 0 0
  1. //: A UIKit based Playground for presenting user interface
  2.  
  3. import UIKit
  4. import PlaygroundSupport
  5.  
  6. // Models
  7.  
  8. struct MyViewModel: Equatable { let text: String }
  9.  
  10. enum MyError: Error, Equatable {
  11. case noConnection(String)
  12. }
  13.  
  14. // Protocols
  15.  
  16. protocol ViewState: Equatable {
  17. associatedtype T: Equatable
  18. associatedtype Error: Equatable
  19. var isLoading: Bool { get }
  20. var data: T? { get }
  21. var error: Error? { get }
  22. }
  23.  
  24. protocol Presenting {
  25. func loadData()
  26. }
  27.  
  28. protocol UI: class {
  29. associatedtype State
  30. func render(state: State)
  31. }
  32.  
  33. // Base Classes
  34. class Presenter<V: UI> {
  35. weak var ui: V?
  36. }
  37.  
  38. // Module Classes
  39.  
  40. final class MyPresenter: Presenter<MyView>, Presenting {
  41. func loadData() {
  42. ui?.render(state: .loading)
  43. DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
  44. self.ui?.render(state: .error(.noConnection("oops, we messed up!")))
  45. }
  46. DispatchQueue.main.asyncAfter(deadline: .now() + 4) {
  47. self.ui?.render(state: .loaded(.init(text: "kidding..got some data")))
  48. }
  49. }
  50. }
  51.  
  52. class MyView : UIViewController {
  53. let presenter: MyPresenter
  54. var lable: UILabel!
  55.  
  56. init(presenter: MyPresenter = MyPresenter()) {
  57. self.presenter = presenter
  58. super.init(nibName: nil, bundle: nil)
  59. presenter.ui = self
  60. }
  61.  
  62. required init?(coder aDecoder: NSCoder) {
  63. fatalError("init(coder:) has not been implemented")
  64. }
  65.  
  66. override func loadView() {
  67. let view = UIView()
  68. view.backgroundColor = .white
  69.  
  70. let label = UILabel()
  71. label.frame = CGRect(x: 150, y: 200, width: 250, height: 20)
  72. label.text = "Hello World!"
  73. label.textColor = .black
  74.  
  75. view.addSubview(label)
  76. self.lable = label
  77. self.view = view
  78. }
  79.  
  80. override func viewDidAppear(_ animated: Bool) {
  81. super.viewDidAppear(animated)
  82. presenter.loadData()
  83. }
  84.  
  85. private func showSpinner() {
  86. lable.textColor = .gray
  87. lable.text = "..loading"
  88. }
  89.  
  90. private func show(data: MyViewModel) {
  91. lable.textColor = .black
  92. lable.text = data.text
  93. }
  94.  
  95. private func show(error: MyError) {
  96. lable.textColor = .red
  97. switch error {
  98. case .noConnection(let mesg):
  99. lable.text = mesg
  100. }
  101. }
  102. }
  103.  
  104. extension MyView: UI {
  105. typealias T = State
  106. func render(state: State) {
  107. switch state {
  108. case .loading: showSpinner()
  109. case .loaded(let data): show(data: data)
  110. case .error(let error): show(error: error)
  111. }
  112. }
  113. }
  114.  
  115. extension MyView {
  116. enum State {
  117. typealias T = MyViewModel
  118. typealias Error = MyError
  119. case loading, loaded(T), error(Error)
  120. }
  121. }
  122.  
  123. extension MyView.State: ViewState {
  124. var isLoading: Bool { return self == .loading }
  125. var data: MyViewModel? {
  126. switch self {
  127. case .loading, .error: return nil
  128. case .loaded(let data): return data
  129. }
  130. }
  131. var error: MyError? {
  132. switch self {
  133. case .loading, .loaded: return nil
  134. case .error(let mesg): return mesg
  135. }
  136. }
  137. }
  138.  
  139. // Present the view controller in the Live View window
  140. PlaygroundPage.current.liveView = MyView()
Add Comment
Please, Sign In to add comment