@@ -0,0 +1,14 @@ | |||||
Pod::Spec.new do |s| | |||||
s.name = 'MPAKX' | |||||
s.version = '2023.12.15' | |||||
s.license = 'IVCS' | |||||
s.summary = 'IVCS' | |||||
s.homepage = 'IVCS' | |||||
s.author = 'IVCS' | |||||
s.source = { :git => 'https://fake.com/FAKE.git', :tag => s.version } | |||||
s.source_files = 'src/*.swift' | |||||
s.swift_version = '5.2' | |||||
s.ios.deployment_target = '14.0' | |||||
end |
@@ -0,0 +1,21 @@ | |||||
// swift-tools-version: 5.9 | |||||
import PackageDescription | |||||
let package = Package( | |||||
name: "MPAKX", | |||||
platforms: [.iOS(.v14)], | |||||
products: [ | |||||
.library( | |||||
name: "MPAKX", | |||||
type: .dynamic, | |||||
targets: ["MPAKX"] | |||||
), | |||||
], | |||||
targets: [ | |||||
.target( | |||||
name: "MPAKX", | |||||
path: "src" | |||||
), | |||||
] | |||||
) |
@@ -0,0 +1 @@ | |||||
Сущности для уменьшения количества кода при использовании архитектуры "Мрак в Моделях" |
@@ -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)") | |||||
} | |||||
} | |||||
} |
@@ -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 | |||||
} | |||||
} | |||||
} |
@@ -12,5 +12,6 @@ s.swift_version = '5.2' | |||||
s.ios.deployment_target = '14.0' | s.ios.deployment_target = '14.0' | ||||
s.dependency 'BusX' | s.dependency 'BusX' | ||||
s.dependency 'CordX' | s.dependency 'CordX' | ||||
s.dependency 'MPAKX' | |||||
end | end |
@@ -6,6 +6,7 @@ platform :ios, '14.0' | |||||
pod 'BusX', :path => '../Modules/BusX' | pod 'BusX', :path => '../Modules/BusX' | ||||
pod 'CordX', :path => '../Modules/CordX' | pod 'CordX', :path => '../Modules/CordX' | ||||
pod 'MeetupIdX', :path => '../Modules/MeetupIdX' | pod 'MeetupIdX', :path => '../Modules/MeetupIdX' | ||||
pod 'MPAKX', :path => '../Modules/MPAKX' | |||||
target 'pesochnicza' do | target 'pesochnicza' do | ||||
use_frameworks! | use_frameworks! | ||||
@@ -5,11 +5,14 @@ PODS: | |||||
- MeetupIdX (2023.12.28): | - MeetupIdX (2023.12.28): | ||||
- BusX | - BusX | ||||
- CordX | - CordX | ||||
- MPAKX | |||||
- MPAKX (2023.12.15) | |||||
DEPENDENCIES: | DEPENDENCIES: | ||||
- BusX (from `../Modules/BusX`) | - BusX (from `../Modules/BusX`) | ||||
- CordX (from `../Modules/CordX`) | - CordX (from `../Modules/CordX`) | ||||
- MeetupIdX (from `../Modules/MeetupIdX`) | - MeetupIdX (from `../Modules/MeetupIdX`) | ||||
- MPAKX (from `../Modules/MPAKX`) | |||||
EXTERNAL SOURCES: | EXTERNAL SOURCES: | ||||
BusX: | BusX: | ||||
@@ -18,12 +21,15 @@ EXTERNAL SOURCES: | |||||
:path: "../Modules/CordX" | :path: "../Modules/CordX" | ||||
MeetupIdX: | MeetupIdX: | ||||
:path: "../Modules/MeetupIdX" | :path: "../Modules/MeetupIdX" | ||||
MPAKX: | |||||
:path: "../Modules/MPAKX" | |||||
SPEC CHECKSUMS: | SPEC CHECKSUMS: | ||||
BusX: fd22c04ad544d131e66315c1a33d87d85b19712e | BusX: fd22c04ad544d131e66315c1a33d87d85b19712e | ||||
CordX: 63515d366b217366b9562edcfef34630a7be1171 | CordX: 63515d366b217366b9562edcfef34630a7be1171 | ||||
MeetupIdX: 2492aa1705abcda355a2a737bc11a36f25f95cf5 | |||||
MeetupIdX: 73bad884d8b9475a9f68c5bfbc41fd801bcd9bff | |||||
MPAKX: dc592434f55edf34709f6e4f37c9ec90dcd95185 | |||||
PODFILE CHECKSUM: cc90c0545c91b88d241373031398c5b3c4dc6663 | |||||
PODFILE CHECKSUM: dec392687416132036b0dfd3d25285cb6aa81629 | |||||
COCOAPODS: 1.13.0 | COCOAPODS: 1.13.0 |