-
-
Save maximkrouk/8ab244d618158199ffe2160d29818915 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Combine | |
import ComposableArchitecture | |
import DeclarativeConfiguration | |
import SwiftUI | |
public protocol ComposableCoreProtocol { | |
associatedtype State | |
associatedtype Action | |
var store: ComposableArchitecture.Store<State, Action>? { get } | |
var viewStore: ComposableArchitecture.ViewStore<State, Action>? { get } | |
} | |
extension ComposableCoreProtocol { | |
public typealias Store = ComposableArchitecture.Store<State, Action> | |
public typealias ViewStore = ComposableArchitecture.ViewStore<State, Action> | |
public typealias Subscriptions = Set<AnyCancellable> | |
} | |
/// Protocol that enables you to use composable core and provides convenient typealiases for it | |
public protocol ComposableCoreProvider { | |
associatedtype State: Equatable | |
associatedtype Action | |
var core: ComposableCore<State, Action> { get } | |
} | |
extension ComposableCoreProvider { | |
public typealias Core = ComposableCore<State, Action> | |
public typealias Store = Core.Store | |
public typealias ViewStore = Core.ViewStore | |
} | |
public class ComposableCore<State: Equatable, Action>: ComposableCoreProtocol { | |
public typealias Store = ComposableArchitecture.Store<State, Action> | |
public typealias ViewStore = ComposableArchitecture.ViewStore<State, Action> | |
public typealias StorePublisher = ComposableArchitecture.StorePublisher<State> | |
public typealias Subscriptions = Set<AnyCancellable> | |
public var state: State? { viewStore?.state } | |
private(set) public var store: Store? | |
private(set) public var viewStore: ViewStore? | |
private var localSubscriptions: Subscriptions = [] | |
private var stateSubscriptions: Subscriptions = [] | |
private let lock = NSLock() | |
private var _bind: ((StorePublisher, inout Subscriptions) -> Void)? | |
/// Handler for state rebinding on the `setStore` method call | |
public func bind(perfrom action: ((StorePublisher, inout Subscriptions) -> Void)?) { | |
self._bind = action | |
} | |
/// Handler for state rebinding on the `setStore` method call | |
@Handler<Store?> | |
public var scope | |
/// Handler for the `setStore` method | |
@Handler2<Store?, Store?> | |
public var storeWillSet | |
/// Handler for the `setStore` method completion | |
@Handler2<Store?, Store?> | |
public var storeWasSet | |
public init() {} | |
public func setStore(_ store: ComposableArchitecture.Store<State?, Action>) { | |
localSubscriptions.removeAll() | |
store.ifLet( | |
then: { [weak self] store in | |
self?.setStore(store) | |
}, | |
else: { [weak self] in | |
self?.setStore(nil) | |
} | |
).store(in: &localSubscriptions) | |
} | |
public func setStore(_ store: Store?) { | |
localSubscriptions.removeAll() | |
let oldStore = self.store | |
self._storeWillSet(oldStore, store) | |
self.store = store | |
self.viewStore = store.map(ViewStore.init) | |
self._scope(store) | |
self.subscribeToStateChanges() | |
self._storeWasSet(oldStore, store) | |
} | |
public func subscribeToStateChanges() { | |
lock.lock() | |
stateSubscriptions.removeAll() | |
if let statePublishser = viewStore?.publisher { | |
_bind?(statePublishser, &stateSubscriptions) | |
} | |
lock.unlock() | |
} | |
public func send(_ action: Action) { | |
viewStore.map { $0.send(action) } | |
} | |
public func send(_ action: Action, animation: Animation?) { | |
viewStore.map { $0.send(action, animation: animation) } | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import ComposableArchitecture | |
import Combine | |
public protocol ComposableObjectProtocol: NSObject, ComposableCoreProvider { | |
func commonInit() | |
func scope(_ store: Store?) | |
func storeWillSet( | |
from oldStore: Store?, | |
to newStore: Store? | |
) | |
func storeWasSet( | |
from oldStore: Store?, | |
to newStore: Store? | |
) | |
func bind( | |
_ state: StorePublisher<State>, | |
into subscriptions: inout Core.Subscriptions | |
) | |
} | |
extension ComposableObjectProtocol { | |
public func __setupCore() { | |
core.scope { [weak self] store in | |
self?.scope(store) | |
} | |
core.storeWillSet { [weak self] old, new in | |
self?.storeWillSet(from: old, to: new) | |
} | |
core.storeWasSet { [weak self] old, new in | |
self?.storeWasSet(from: old, to: new) | |
} | |
core.bind { [weak self] state, subscriptions in | |
self?.bind(state, into: &subscriptions) | |
} | |
} | |
} | |
open class NSComposableObject<State: Equatable, Action>: NSObject, ComposableObjectProtocol { | |
public let core: ComposableCore<State, Action> = .init() | |
public var subscriptions: Set<AnyCancellable> = [] | |
public override init() { | |
super.init() | |
commonInit() | |
} | |
open func commonInit() { | |
__setupCore() | |
} | |
open func scope(_ store: Store<State, Action>?) {} | |
open func storeWillSet( | |
from oldStore: Store<State, Action>?, | |
to newStore: Store<State, Action>? | |
) {} | |
open func storeWasSet( | |
from oldStore: Store<State, Action>?, | |
to newStore: Store<State, Action>? | |
) {} | |
open func bind( | |
_ state: StorePublisher<State>, | |
into subscriptions: inout Core.Subscriptions | |
) {} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Back to index