This commit is contained in:
Михаил Капелько
2023-12-25 18:54:25 +03:00
parent 06c143efb4
commit 880c4f3dee
2 changed files with 74 additions and 45 deletions

View File

@@ -3,11 +3,17 @@ import Foundation
public enum Bus { } public enum Bus { }
public extension Bus {
enum Option {
case async
}
}
extension Bus { extension Bus {
final class Service { final class Service {
static let singleton = Service() static let singleton = Service()
let events = PassthroughSubject<(key: String, value: Any), Never>() let events = PassthroughSubject<(key: String, value: Any), Never>()
var subscriptions = Set<AnyCancellable>() var subscriptions = [AnyCancellable]()
func send(_ key: String, _ value: Any) { func send(_ key: String, _ value: Any) {
/**/print("ИГР BusS.send key/value: '\(key)'/'\(value)'") /**/print("ИГР BusS.send key/value: '\(key)'/'\(value)'")
@@ -17,48 +23,56 @@ extension Bus {
} }
public extension Bus { public extension Bus {
static func receiveAsync<T>( static func receive<T>(
_ subscriptions: inout Set<AnyCancellable>,
_ keys: Set<String>, _ keys: Set<String>,
_ handler: @escaping ((String, T) -> Void) _ handler: @escaping ((String, T) -> Void),
opt: [Option] = [],
sub: UnsafeMutablePointer<[AnyCancellable]>? = nil
) { ) {
Service.singleton.events var subscription: AnyCancellable?
.compactMap { convertKeyValue(keys, $0) } let isAsync = opt.contains(.async)
.receive(on: DispatchQueue.main)
.sink { v in handler(v.0, v.1) } // Async.
.store(in: &subscriptions) 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 receiveSync<T>( static func send<T>(
_ subscriptions: inout Set<AnyCancellable>,
_ keys: Set<String>,
_ 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<T>(
_ subscriptions: inout Set<AnyCancellable>,
_ key: String, _ key: String,
_ node: AnyPublisher<T, Never> _ node: AnyPublisher<T, Never>,
opt: [Option] = [],
sub: UnsafeMutablePointer<[AnyCancellable]>? = nil
) { ) {
node var subscription: AnyCancellable?
.receive(on: DispatchQueue.main) let isAsync = opt.contains(.async)
.sink { v in Service.singleton.send(key, v) }
.store(in: &subscriptions) // Async.
} if isAsync {
subscription = node
static func sendSync<T>( .receive(on: DispatchQueue.main)
_ subscriptions: inout Set<AnyCancellable>, .sink { v in Service.singleton.send(key, v) }
_ key: String, }
_ node: AnyPublisher<T, Never>
) { // Sync.
node if !isAsync {
.sink { v in Service.singleton.send(key, v) } subscription = node
.store(in: &subscriptions) .sink { v in Service.singleton.send(key, v) }
}
subscribe(subscription, sub)
} }
static func send(_ key: String, _ value: Any) { 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 { public extension Bus {
static func processSync<Src, Dst>( static func processSync<Src, Dst>(
_ subscriptions: inout Set<AnyCancellable>, _ subscriptions: inout [AnyCancellable],
_ handler: @escaping ((Src) -> Dst?), _ handler: @escaping ((Src) -> Dst?),
_ keyIn: String, _ keyIn: String,
_ keyOut: String _ keyOut: String

View File

@@ -4,11 +4,10 @@ import SwiftUI
final class VM: ObservableObject { final class VM: ObservableObject {
@Published var text = "a:" @Published var text = "a:"
var subscriptions = Set<AnyCancellable>() var subscriptions = [AnyCancellable]()
init() { init() {
Bus.sendSync( Bus.send(
&subscriptions,
MeetupId.K.meetupIdTextUI.rawValue, MeetupId.K.meetupIdTextUI.rawValue,
$text $text
// Исключаем конфликты от UI и App путём игнорирования спама. // Исключаем конфликты от UI и App путём игнорирования спама.
@@ -17,13 +16,15 @@ final class VM: ObservableObject {
.filter { $0.hasPrefix("u:") } .filter { $0.hasPrefix("u:") }
// Убираем источник. // Убираем источник.
.map { String($0.dropFirst(2)) } .map { String($0.dropFirst(2)) }
.eraseToAnyPublisher() .eraseToAnyPublisher(),
sub: &subscriptions
) )
Bus.receiveAsync( Bus.receive(
&subscriptions,
[MeetupId.K.meetupIdTextApp.rawValue], [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
) )
} }
} }