This commit is contained in:
Михаил Капелько
2023-12-28 14:13:38 +03:00
parent 853686f441
commit 24bc62145f
8 changed files with 184 additions and 2 deletions

View File

@@ -0,0 +1,128 @@
import Combine
import Foundation
public protocol MPAKControllerProtocol: AnyObject {
associatedtype Model
func pipe<T>(
dbg: String?,
sub: UnsafeMutablePointer<[AnyCancellable]>?,
_ node: AnyPublisher<T, Never>,
_ reaction: @escaping (inout Model) -> Void,
_ reversion: ((inout Model) -> Void)?
)
func pipeValue<T>(
dbg: String?,
sub: UnsafeMutablePointer<[AnyCancellable]>?,
_ node: AnyPublisher<T, Never>,
_ reaction: @escaping (inout Model, T) -> Void,
_ reversion: ((inout Model, T) -> Void)?
)
}
extension MPAK {
open class Controller<Model>: MPAKControllerProtocol {
public let m: CurrentValueSubject<Model, Never>
public var subscriptions = [AnyCancellable]()
private var debugClassName: String?
private var debugLog: ((String) -> Void)?
private var model: Model
public init(
_ model: Model,
debugClassName: String? = nil,
debugLog: ((String) -> Void)? = nil
) {
m = .init(model)
self.model = model
self.debugClassName = debugClassName
self.debugLog = debugLog
}
public func pipe<T>(
dbg: String? = nil,
sub: UnsafeMutablePointer<[AnyCancellable]>? = nil,
_ node: AnyPublisher<T, Never>,
_ reaction: @escaping (inout Model) -> Void,
_ reversion: ((inout Model) -> Void)? = nil
) {
let subscription = node
.sink { [weak self] _ in
assert(Thread.isMainThread)
guard let self = self else { return }
self.dbgLog(dbg)
reaction(&self.model)
let modelCopy = self.model
if let rev = reversion {
rev(&self.model)
}
self.m.send(modelCopy)
}
if let sub = sub {
sub.pointee.append(subscription)
} else {
subscriptions.append(subscription)
}
}
public func pipeOptional<T>(
dbg: String? = nil,
_ node: AnyPublisher<T?, Never>,
_ reaction: @escaping (inout Model, T?) -> Void,
_ reversion: ((inout Model, T?) -> Void)? = nil
) {
node
.sink { [weak self] value in
assert(Thread.isMainThread)
guard let self = self else { return }
self.dbgLog(dbg)
reaction(&self.model, value)
let modelCopy = self.model
if let rev = reversion {
rev(&self.model, value)
}
self.m.send(modelCopy)
}
.store(in: &subscriptions)
}
public func pipeValue<T>(
dbg: String? = nil,
sub: UnsafeMutablePointer<[AnyCancellable]>? = nil,
_ node: AnyPublisher<T, Never>,
_ reaction: @escaping (inout Model, T) -> Void,
_ reversion: ((inout Model, T) -> Void)? = nil
) {
let subscription = node
.sink { [weak self] value in
assert(Thread.isMainThread)
guard let self = self else { return }
self.dbgLog(dbg)
reaction(&self.model, value)
let modelCopy = self.model
if let rev = reversion {
rev(&self.model, value)
}
self.m.send(modelCopy)
}
if let sub = sub {
sub.pointee.append(subscription)
} else {
subscriptions.append(subscription)
}
}
private func dbgLog(_ text: String?) {
guard
let className = debugClassName,
let log = debugLog,
let text = text
else {
return
}
log("\(className).\(text)")
}
}
}

View File

@@ -0,0 +1,10 @@
public enum MPAK {
public struct Recent<T> {
public var isRecent = false
public var value: T
public init(_ value: T) {
self.value = value
}
}
}