diff --git a/src/Bus.swift b/src/Bus.swift index ee132b3..e33a09d 100644 --- a/src/Bus.swift +++ b/src/Bus.swift @@ -3,11 +3,17 @@ import Foundation public enum Bus { } +public extension Bus { + enum Option { + case async + } +} + extension Bus { final class Service { static let singleton = Service() let events = PassthroughSubject<(key: String, value: Any), Never>() - var subscriptions = Set() + var subscriptions = [AnyCancellable]() func send(_ key: String, _ value: Any) { /**/print("ИГР BusS.send key/value: '\(key)'/'\(value)'") @@ -17,48 +23,56 @@ extension Bus { } public extension Bus { - static func receiveAsync( - _ subscriptions: inout Set, + static func receive( _ keys: Set, - _ handler: @escaping ((String, T) -> Void) + _ handler: @escaping ((String, T) -> Void), + opt: [Option] = [], + sub: UnsafeMutablePointer<[AnyCancellable]>? = nil ) { - Service.singleton.events - .compactMap { convertKeyValue(keys, $0) } - .receive(on: DispatchQueue.main) - .sink { v in handler(v.0, v.1) } - .store(in: &subscriptions) - } + var subscription: AnyCancellable? + let isAsync = opt.contains(.async) - static func receiveSync( - _ subscriptions: inout Set, - _ keys: Set, - _ handler: @escaping ((String, T) -> Void) - ) { - Service.singleton.events - .compactMap { convertKeyValue(keys, $0) } - .sink { v in handler(v.0, v.1) } - .store(in: &subscriptions) - } - - static func sendAsync( - _ subscriptions: inout Set, - _ key: String, - _ node: AnyPublisher - ) { - node - .receive(on: DispatchQueue.main) - .sink { v in Service.singleton.send(key, v) } - .store(in: &subscriptions) + // Async. + if isAsync { + subscription = Service.singleton.events + .compactMap { convertKeyValue(keys, $0) } + .receive(on: DispatchQueue.main) + .sink { v in handler(v.0, v.1) } + } + + // Async. + if !isAsync { + subscription = Service.singleton.events + .compactMap { convertKeyValue(keys, $0) } + .sink { v in handler(v.0, v.1) } + } + + subscribe(subscription, sub) } - - static func sendSync( - _ subscriptions: inout Set, + + static func send( _ key: String, - _ node: AnyPublisher + _ node: AnyPublisher, + opt: [Option] = [], + sub: UnsafeMutablePointer<[AnyCancellable]>? = nil ) { - node - .sink { v in Service.singleton.send(key, v) } - .store(in: &subscriptions) + var subscription: AnyCancellable? + let isAsync = opt.contains(.async) + + // Async. + if isAsync { + subscription = node + .receive(on: DispatchQueue.main) + .sink { v in Service.singleton.send(key, v) } + } + + // Sync. + if !isAsync { + subscription = node + .sink { v in Service.singleton.send(key, v) } + } + + subscribe(subscription, sub) } static func send(_ key: String, _ value: Any) { @@ -66,9 +80,23 @@ public extension Bus { } } +private extension Bus { + static func subscribe( + _ subscription: AnyCancellable?, + _ sub: UnsafeMutablePointer<[AnyCancellable]>? + ) { + guard let subscription else { return } + if let sub = sub { + sub.pointee.append(subscription) + } else { + Service.singleton.subscriptions.append(subscription) + } + } +} + public extension Bus { static func processSync( - _ subscriptions: inout Set, + _ subscriptions: inout [AnyCancellable], _ handler: @escaping ((Src) -> Dst?), _ keyIn: String, _ keyOut: String diff --git a/src/VM.swift b/src/VM.swift index 5fbce07..9086bfc 100644 --- a/src/VM.swift +++ b/src/VM.swift @@ -4,11 +4,10 @@ import SwiftUI final class VM: ObservableObject { @Published var text = "a:" - var subscriptions = Set() + var subscriptions = [AnyCancellable]() init() { - Bus.sendSync( - &subscriptions, + Bus.send( MeetupId.K.meetupIdTextUI.rawValue, $text // Исключаем конфликты от UI и App путём игнорирования спама. @@ -17,13 +16,15 @@ final class VM: ObservableObject { .filter { $0.hasPrefix("u:") } // Убираем источник. .map { String($0.dropFirst(2)) } - .eraseToAnyPublisher() + .eraseToAnyPublisher(), + sub: &subscriptions ) - Bus.receiveAsync( - &subscriptions, + Bus.receive( [MeetupId.K.meetupIdTextApp.rawValue], - { [weak self] (_, v: String) in self?.text = "a:\(v)" } + { [weak self] (_, v: String) in self?.text = "a:\(v)" }, + opt: [.async], + sub: &subscriptions ) } }