// // ModelHanlderPublisher.swift // VDS // // Created by Matt Bruce on 8/12/22. // import Foundation import Combine extension Publishers { public struct ModelHandlerPublisher: Publisher { public typealias Output = ModelHandlerType.ModelType public typealias Failure = Never private let modelHandler: ModelHandlerType public init(modelHandler: ModelHandlerType) { self.modelHandler = modelHandler } public func receive(subscriber: S) where S : Subscriber, Never == S.Failure, ModelHandlerType.ModelType == S.Input { let subscription = ModelHandlerSubscription(subscriber: subscriber, modelHandler: modelHandler) subscriber.receive(subscription: subscription) } } public class ModelHandlerSubscription: Subscription where S.Input == ModelHandlerType.ModelType, S.Failure == Never { private var subscriber: S? private var modelHandler: ModelHandlerType? public var subscribers = Set() public init(subscriber: S, modelHandler: ModelHandlerType) { self.subscriber = subscriber self.modelHandler = modelHandler subscribe() } public func request(_ demand: Subscribers.Demand) { } public func cancel() { subscriber = nil modelHandler = nil } private func subscribe() { guard let publisher = modelHandler?.modelPublisher else { return } publisher.debounce(for: .seconds(Constants.ModelStateDebounce), scheduler: RunLoop.main).sink { [weak self] viewModel in guard let self else { return } _ = self.subscriber?.receive(viewModel) }.store(in: &subscribers) } } } extension ModelHandlerable { public var handlerPublisher: Publishers.ModelHandlerPublisher { return Publishers.ModelHandlerPublisher(modelHandler: self) } public func createBinding(with subject: CurrentValueSubject, storeIn subscriptions: inout Set) { handlerPublisher.sink { (value) in subject.send(value) }.store(in: &subscriptions) } }