Михаил Капелько 10 months ago
parent
commit
1779eb3efe
15 changed files with 3 additions and 320 deletions
  1. +1
    -0
      Modules/BusX
  2. +0
    -31
      Modules/BusX/Bus/src/Bus.Async.swift
  3. +0
    -29
      Modules/BusX/Bus/src/Bus.Aux.swift
  4. +0
    -31
      Modules/BusX/Bus/src/Bus.Debounce.swift
  5. +0
    -31
      Modules/BusX/Bus/src/Bus.Delay.swift
  6. +0
    -29
      Modules/BusX/Bus/src/Bus.Sync.swift
  7. +0
    -56
      Modules/BusX/Bus/src/Bus.swift
  8. +0
    -9
      Modules/BusX/BusUI/src/BusUI.Aux.swift
  9. +0
    -16
      Modules/BusX/BusUI/src/BusUI.Button.swift
  10. +0
    -29
      Modules/BusX/BusUI/src/BusUI.TextField.swift
  11. +0
    -22
      Modules/BusX/BusUI/src/BusUI.TextFieldSource.swift
  12. +0
    -20
      Modules/BusX/BusUI/src/BusUI.Value.swift
  13. +0
    -1
      Modules/BusX/BusUI/src/BusUI.swift
  14. +0
    -14
      Modules/BusX/BusX.podspec
  15. +2
    -2
      app/Podfile.lock

+ 1
- 0
Modules/BusX View File

@@ -0,0 +1 @@
../../../../u/Modules/BusX

+ 0
- 31
Modules/BusX/Bus/src/Bus.Async.swift View File

@@ -1,31 +0,0 @@
import Combine

public extension Bus {
final class Async<Src, Dst> {
let v = PassthroughSubject<Src, Never>()
var subscriptions = [AnyCancellable]()

public init(
_ handler: @escaping ((Src) -> Dst?),
_ src: String,
_ dst: String
) {
// Вход.
Bus.receiveSync(
[src],
{ [weak self] _, v in self?.v.send(v) },
&subscriptions
)
// Выход.
Bus.sendSync(
dst,
v
.compactMap { (v: Src) in handler(v) }
// Асинхронно.
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher(),
&subscriptions
)
}
}
}

+ 0
- 29
Modules/BusX/Bus/src/Bus.Aux.swift View File

@@ -1,29 +0,0 @@
public extension Bus {
/// Пропускаем далее единственный ключ.
static func convertKeyValue<T>(
_ key: String,
_ v: (key: String, value: Any)
) -> (String, T)? {
guard
key == v.key,
let value = v.value as? T
else {
return nil
}
return (key, value)
}

/// Пропускаем далее множество ключей.
static func convertKeyValue<T>(
_ keys: Set<String>,
_ v: (key: String, value: Any)
) -> (String, T)? {
guard
keys.contains(v.key),
let value = v.value as? T
else {
return nil
}
return (v.key, value)
}
}

+ 0
- 31
Modules/BusX/Bus/src/Bus.Debounce.swift View File

@@ -1,31 +0,0 @@
import Combine

public extension Bus {
final class Debounce<Src, Dst> {
let v = PassthroughSubject<Src, Never>()
var subscriptions = [AnyCancellable]()

public init(
_ handler: @escaping ((Src) -> Dst?),
_ sec: Double,
_ src: String,
_ dst: String
) {
// Вход.
Bus.receiveSync(
[src],
{ [weak self] _, v in self?.v.send(v) },
&subscriptions
)
// Выход.
Bus.sendSync(
dst,
v
.debounce(for: .seconds(sec), scheduler: DispatchQueue.main)
.compactMap { (v: Src) in handler(v) }
.eraseToAnyPublisher(),
&subscriptions
)
}
}
}

+ 0
- 31
Modules/BusX/Bus/src/Bus.Delay.swift View File

@@ -1,31 +0,0 @@
import Combine

public extension Bus {
final class Delay<Src, Dst> {
let v = PassthroughSubject<Src, Never>()
var subscriptions = [AnyCancellable]()

public init(
_ handler: @escaping ((Src) -> Dst?),
_ sec: Double,
_ src: String,
_ dst: String
) {
// Вход.
Bus.receiveSync(
[src],
{ [weak self] _, v in self?.v.send(v) },
&subscriptions
)
// Выход.
Bus.sendSync(
dst,
v
.delay(for: .seconds(sec), scheduler: DispatchQueue.main)
.compactMap { (v: Src) in handler(v) }
.eraseToAnyPublisher(),
&subscriptions
)
}
}
}

+ 0
- 29
Modules/BusX/Bus/src/Bus.Sync.swift View File

@@ -1,29 +0,0 @@
import Combine

public extension Bus {
final class Sync<Src, Dst> {
let v = PassthroughSubject<Src, Never>()
var subscriptions = [AnyCancellable]()

public init(
_ handler: @escaping ((Src) -> Dst?),
_ src: String,
_ dst: String
) {
// Вход.
Bus.receiveSync(
[src],
{ [weak self] _, v in self?.v.send(v) },
&subscriptions
)
// Выход.
Bus.sendSync(
dst,
v
.compactMap { (v: Src) in handler(v) }
.eraseToAnyPublisher(),
&subscriptions
)
}
}
}

+ 0
- 56
Modules/BusX/Bus/src/Bus.swift View File

@@ -1,56 +0,0 @@
import Combine
import Foundation

public enum Bus {
private static let e = PassthroughSubject<(key: String, value: Any), Never>()

public static var events: AnyPublisher<(key: String, value: Any), Never> {
e.eraseToAnyPublisher()
}
}

public extension Bus {
/// Асинхронно обрабатываем входящие события из шины.
static func receiveAsync<T>(
_ keys: Set<String>,
_ handler: @escaping ((String, T) -> Void),
_ subscriptions: inout [AnyCancellable]
) {
e
.compactMap { convertKeyValue(keys, $0) }
.receive(on: DispatchQueue.main)
.sink { v in handler(v.0, v.1) }
.store(in: &subscriptions)
}
/// Синхронно обрабатываем входящие события из шины.
static func receiveSync<T>(
_ keys: Set<String>,
_ handler: @escaping ((String, T) -> Void),
_ subscriptions: inout [AnyCancellable]
) {
e
.compactMap { convertKeyValue(keys, $0) }
.sink { v in handler(v.0, v.1) }
.store(in: &subscriptions)
}

/// Синхронно отправляем события из узла в шину.
///
/// Для асинхронной отправки достаточно добавить оператор `receive(on:)`
/// в цепочке параметра `node`
static func sendSync<T>(
_ key: String,
_ node: AnyPublisher<T, Never>,
_ subscriptions: inout [AnyCancellable]
) {
node
.sink { v in e.send((key, v)) }
.store(in: &subscriptions)
}
/// Единоразово синхронно отправляем событие в шину.
static func send(_ key: String, _ value: Any) {
e.send((key, value))
}
}

+ 0
- 9
Modules/BusX/BusUI/src/BusUI.Aux.swift View File

@@ -1,9 +0,0 @@
extension BusUI {
/// Пропускаем лишь значения от UI
///
/// - Returns: Значение без префиксов "a:"/"u:"
static func onlyUIText(_ s: String) -> String? {
guard s.hasPrefix("u:") else { return nil }
return String(s.dropFirst(2))
}
}

+ 0
- 16
Modules/BusX/BusUI/src/BusUI.Button.swift View File

@@ -1,16 +0,0 @@
import Combine

extension BusUI {
public final class Button: ObservableObject {
public let v = PassthroughSubject<Void, Never>()
var subscriptions = [AnyCancellable]()
public init(_ key: String) {
Bus.sendSync(
key,
v.map { true }.eraseToAnyPublisher(),
&subscriptions
)
}
}
}

+ 0
- 29
Modules/BusX/BusUI/src/BusUI.TextField.swift View File

@@ -1,29 +0,0 @@
import Combine
import SwiftUI

extension BusUI {
public final class TextField: ObservableObject {
@Published public var v = "a:"
var subscriptions = [AnyCancellable]()
public init(
_ textApp: String,
_ textUI: String
) {
Bus.sendSync(
textUI,
$v
.removeDuplicates()
.compactMap(onlyUIText)
.eraseToAnyPublisher(),
&subscriptions
)
Bus.receiveSync(
[textApp],
{ [weak self] (_, v: String) in self?.v = "a:\(v)" },
&subscriptions
)
}
}
}

+ 0
- 22
Modules/BusX/BusUI/src/BusUI.TextFieldSource.swift View File

@@ -1,22 +0,0 @@
import Foundation

extension BusUI {
public final class TextFieldSource: Formatter {
/// Выдаём для отображения очищенную от источника строку.
public override func string(for obj: Any?) -> String? {
guard let str = obj as? String else { return nil }
return String(str.dropFirst(2))
}

/// Выдаём для использования кодом строку с указанием источника
/// в виде пользователя `u:`
public override func getObjectValue(
_ obj: AutoreleasingUnsafeMutablePointer<AnyObject?>?,
for string: String,
errorDescription error: AutoreleasingUnsafeMutablePointer<NSString?>?
) -> Bool {
obj?.pointee = "u:\(string)" as AnyObject
return true
}
}
}

+ 0
- 20
Modules/BusX/BusUI/src/BusUI.Value.swift View File

@@ -1,20 +0,0 @@
import Combine

extension BusUI {
public final class Value<T>: ObservableObject {
@Published public var v: T
var subscriptions = [AnyCancellable]()
public init(
_ key: String,
_ defaultValue: T
) {
v = defaultValue
Bus.receiveSync(
[key],
{ [weak self] (_, v: T) in self?.v = v },
&subscriptions
)
}
}
}

+ 0
- 1
Modules/BusX/BusUI/src/BusUI.swift View File

@@ -1 +0,0 @@
public enum BusUI { }

+ 0
- 14
Modules/BusX/BusX.podspec View File

@@ -1,14 +0,0 @@
Pod::Spec.new do |s|

s.name = 'BusX'
s.version = '2023.12.30'
s.license = 'IVCS'
s.summary = 'Шина общения элементов приложения'
s.homepage = 'IVCS'
s.author = 'IVCS'
s.source = { :git => 'https://fake.com/FAKE.git', :tag => s.version }
s.source_files = '**/**/*.swift'
s.swift_version = '5.2'
s.ios.deployment_target = '14.0'

end

+ 2
- 2
app/Podfile.lock View File

@@ -1,6 +1,6 @@
PODS:
- AELog (0.6.3)
- BusX (2023.12.30)
- BusX (2024.01.15)
- MeetupIdX (2023.12.31):
- AELog
- BusX
@@ -27,7 +27,7 @@ EXTERNAL SOURCES:

SPEC CHECKSUMS:
AELog: f732b70f7a9d1b4c6a3676304192b3908f362133
BusX: d11e857e9cb762f649ee9f88fd5a4f8fbf5bf96b
BusX: 1db5cf8652f7b206af468cc115cab3326efd1ced
MeetupIdX: 2fa9fb27717aa8878ff495c1abe960c96e524308
MPAKX: dc592434f55edf34709f6e4f37c9ec90dcd95185



Loading…
Cancel
Save