Проверка шаблона шины для iOS

152 lines
4.5KB

  1. import UIKit
  2. @UIApplicationMain
  3. class AppDelegate: UIResponder, UIApplicationDelegate
  4. {
  5. var window: UIWindow?
  6. func application(
  7. _ application: UIApplication,
  8. didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  9. ) -> Bool {
  10. window = UIWindow(frame: UIScreen.main.bounds)
  11. let vc = UIViewController()
  12. addSwiftUIViewAsChild(swiftUIView: V(), parent: vc.view)
  13. vc.view.backgroundColor = .gray
  14. window?.rootViewController = vc
  15. window?.backgroundColor = UIColor.white
  16. window?.makeKeyAndVisible()
  17. return true
  18. }
  19. }
  20. /*
  21. // Bus.Pipe.swift
  22. public extension Bus {
  23. final class BindingPipe<T: Equatable>: ObservableObject {
  24. public let input = PassthroughSubject<T, Never>()
  25. public let output = PassthroughSubject<T, Never>()
  26. @Published var value: T
  27. var isInput = false
  28. var subscriptions = [AnyCancellable]()
  29. deinit {
  30. print("ИГР BusBP.DEinit(\(Unmanaged.passUnretained(self).toOpaque()))")
  31. }
  32. init(
  33. _ defaultValue: T,
  34. _ keyApp: String,
  35. _ keyUI: String
  36. ) {
  37. value = defaultValue
  38. /**/dbg("ИГР BusBP.init(\(Unmanaged.passUnretained(self).toOpaque())) keyA: '\(keyApp)'")
  39. // TextField -> output.
  40. $value
  41. .sink { [weak self] v in
  42. assert(Thread.isMainThread)
  43. // Ignore values received from input.
  44. // Only accept UI provided values.
  45. guard
  46. let self,
  47. !self.isInput
  48. else {
  49. return
  50. }
  51. self.output.send(v)
  52. }
  53. .store(in: &subscriptions)
  54. // input -> TextField.
  55. input
  56. .sink { [weak self] v in
  57. assert(Thread.isMainThread)
  58. guard let self else { return }
  59. /**/dbg("ИГР BusBP.init input: '\(v)'")
  60. self.isInput = true
  61. self.value = v
  62. self.isInput = false
  63. }
  64. .store(in: &subscriptions)
  65. // Оповещаем в мир об изменениях от UI.
  66. Bus.sendAsync(
  67. &subscriptions,
  68. keyUI,
  69. output.eraseToAnyPublisher()
  70. )
  71. Bus.receive(
  72. &subscriptions,
  73. [keyApp],
  74. { [weak self] _, v in
  75. self?.input.send(v)
  76. /**/print("ИГР BusBP.init receive: '\(v)'")
  77. }
  78. )
  79. }
  80. }
  81. }
  82. // BusSlot.swift
  83. var busHolder = Bus.Service()
  84. // ========================================
  85. // MARK: - MeetupX module
  86. // ========================================
  87. enum MeetupId {
  88. enum Keys: String, RawRepresentable {
  89. case meetupIdTextApp
  90. case meetupIdTextUI
  91. }
  92. static func shouldFormat(_ s: String) -> String? {
  93. return s.components(separatedBy: NSCharacterSet.decimalDigits.inverted).reduce("") { $0 + $1 }
  94. }
  95. final class MeetupIdFormatter {
  96. var subscriptions = [AnyCancellable]()
  97. deinit {
  98. /**/dbg("ИГР MeetupIF.DEinit")
  99. }
  100. init() {
  101. Bus.receive(
  102. &subscriptions,
  103. [Keys.meetupIdTextUI.rawValue],
  104. { [weak self] k, v in self?.handleFormatting(k, v) }
  105. )
  106. /**/dbg("ИГР MeetupIF.init")
  107. }
  108. func handleFormatting(_: String, _ value: String) {
  109. let out = MeetupId.shouldFormat(value)
  110. /**/dbg("ИГР MeetupIF.handleF out/dt: '\(out)'/'\(Date())'")
  111. Bus.Service.singleton?.send(Keys.meetupIdTextApp.rawValue, out)
  112. }
  113. }
  114. struct V: View {
  115. /*@StateObject*/ var fmt = MeetupIdFormatter()
  116. @StateObject var txt = Bus.BindingPipe("", Keys.meetupIdTextApp.rawValue, Keys.meetupIdTextUI.rawValue)
  117. var body: some View {
  118. VStack {
  119. Text("Hi, the text is: '\(txt.value)'")
  120. .fontWeight(.bold)
  121. TextField("Placeholder", text: $txt.value)
  122. .padding(8)
  123. .border(Color.blue, width: 2)
  124. }
  125. .frame(width: 320)
  126. .padding()
  127. }
  128. }
  129. }
  130. */