Проверка шаблона шины для iOS
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

129 lines
3.4KB

  1. import Combine
  2. import Foundation
  3. public protocol MPAKControllerProtocol: AnyObject {
  4. associatedtype Model
  5. func pipe<T>(
  6. dbg: String?,
  7. sub: UnsafeMutablePointer<[AnyCancellable]>?,
  8. _ node: AnyPublisher<T, Never>,
  9. _ reaction: @escaping (inout Model) -> Void,
  10. _ reversion: ((inout Model) -> Void)?
  11. )
  12. func pipeValue<T>(
  13. dbg: String?,
  14. sub: UnsafeMutablePointer<[AnyCancellable]>?,
  15. _ node: AnyPublisher<T, Never>,
  16. _ reaction: @escaping (inout Model, T) -> Void,
  17. _ reversion: ((inout Model, T) -> Void)?
  18. )
  19. }
  20. extension MPAK {
  21. open class Controller<Model>: MPAKControllerProtocol {
  22. public let m: CurrentValueSubject<Model, Never>
  23. public var subscriptions = [AnyCancellable]()
  24. private var debugClassName: String?
  25. private var debugLog: ((String) -> Void)?
  26. private var model: Model
  27. public init(
  28. _ model: Model,
  29. debugClassName: String? = nil,
  30. debugLog: ((String) -> Void)? = nil
  31. ) {
  32. m = .init(model)
  33. self.model = model
  34. self.debugClassName = debugClassName
  35. self.debugLog = debugLog
  36. }
  37. public func pipe<T>(
  38. dbg: String? = nil,
  39. sub: UnsafeMutablePointer<[AnyCancellable]>? = nil,
  40. _ node: AnyPublisher<T, Never>,
  41. _ reaction: @escaping (inout Model) -> Void,
  42. _ reversion: ((inout Model) -> Void)? = nil
  43. ) {
  44. let subscription = node
  45. .sink { [weak self] _ in
  46. assert(Thread.isMainThread)
  47. guard let self = self else { return }
  48. self.dbgLog(dbg)
  49. reaction(&self.model)
  50. let modelCopy = self.model
  51. if let rev = reversion {
  52. rev(&self.model)
  53. }
  54. self.m.send(modelCopy)
  55. }
  56. if let sub = sub {
  57. sub.pointee.append(subscription)
  58. } else {
  59. subscriptions.append(subscription)
  60. }
  61. }
  62. public func pipeOptional<T>(
  63. dbg: String? = nil,
  64. _ node: AnyPublisher<T?, Never>,
  65. _ reaction: @escaping (inout Model, T?) -> Void,
  66. _ reversion: ((inout Model, T?) -> Void)? = nil
  67. ) {
  68. node
  69. .sink { [weak self] value in
  70. assert(Thread.isMainThread)
  71. guard let self = self else { return }
  72. self.dbgLog(dbg)
  73. reaction(&self.model, value)
  74. let modelCopy = self.model
  75. if let rev = reversion {
  76. rev(&self.model, value)
  77. }
  78. self.m.send(modelCopy)
  79. }
  80. .store(in: &subscriptions)
  81. }
  82. public func pipeValue<T>(
  83. dbg: String? = nil,
  84. sub: UnsafeMutablePointer<[AnyCancellable]>? = nil,
  85. _ node: AnyPublisher<T, Never>,
  86. _ reaction: @escaping (inout Model, T) -> Void,
  87. _ reversion: ((inout Model, T) -> Void)? = nil
  88. ) {
  89. let subscription = node
  90. .sink { [weak self] value in
  91. assert(Thread.isMainThread)
  92. guard let self = self else { return }
  93. self.dbgLog(dbg)
  94. reaction(&self.model, value)
  95. let modelCopy = self.model
  96. if let rev = reversion {
  97. rev(&self.model, value)
  98. }
  99. self.m.send(modelCopy)
  100. }
  101. if let sub = sub {
  102. sub.pointee.append(subscription)
  103. } else {
  104. subscriptions.append(subscription)
  105. }
  106. }
  107. private func dbgLog(_ text: String?) {
  108. guard
  109. let className = debugClassName,
  110. let log = debugLog,
  111. let text = text
  112. else {
  113. return
  114. }
  115. log("\(className).\(text)")
  116. }
  117. }
  118. }