// // UIControlPublisher.swift // VDS // // Created by Matt Bruce on 8/18/22. // import Foundation import UIKit import Combine /// A custom subscription to capture UIControl target events. public final class UIControlSubscription: Subscription where SubscriberType.Input == Control { private var subscriber: SubscriberType? private let control: Control private let event: UIControl.Event public init(subscriber: SubscriberType, control: Control, event: UIControl.Event) { self.subscriber = subscriber self.control = control self.event = event control.addTarget(self, action: #selector(eventHandler), for: event) } public func request(_ demand: Subscribers.Demand) { // We do nothing here as we only want to send events when they occur. // See, for more info: https://developer.apple.com/documentation/combine/subscribers/demand } public func cancel() { subscriber = nil } @objc private func eventHandler() { _ = subscriber?.receive(control) } } /// A custom `Publisher` to work with our custom `UIControlSubscription`. public struct UIControlPublisher: Publisher { public typealias Output = Control public typealias Failure = Never public let control: Control public let controlEvents: UIControl.Event public init(control: Control, events: UIControl.Event) { self.control = control self.controlEvents = events } /// This function is called to attach the specified `Subscriber` to this `Publisher` by `subscribe(_:)` /// /// - SeeAlso: `subscribe(_:)` /// - Parameters: /// - subscriber: The subscriber to attach to this `Publisher`. /// once attached it can begin to receive values. public func receive(subscriber: S) where S : Subscriber, S.Failure == UIControlPublisher.Failure, S.Input == UIControlPublisher.Output { subscriber.receive(subscription: UIControlSubscription(subscriber: subscriber, control: control, event: controlEvents)) } } /// Extending the `UIControl` types to be able to produce a `UIControl.Event` publisher. public protocol CombineCompatible { } extension UIControl: CombineCompatible { } extension CombineCompatible where Self: UIControl { public func publisher(for events: UIControl.Event) -> UIControlPublisher { return UIControlPublisher(control: self, events: events) } }