vds_ios/VDS/Publishers/UIControlPublisher.swift
Matt Bruce 248caeb480 updated for maintaining a clickable count
Signed-off-by: Matt Bruce <matt.bruce@verizon.com>
2023-03-30 08:43:55 -05:00

84 lines
2.9 KiB
Swift

//
// 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<SubscriberType: Subscriber, Control: UIControl>: 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
//allow highlight for VDS.Controls on "onClick" events
if let c = control as? Clickable, event == .touchUpInside {
c.touchUpInsideCount += 1
}
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
}
deinit {
//remove highlight for VDS.Controls on "onClick" events
if let c = control as? Clickable, event == .touchUpInside, c.touchUpInsideCount > 0 {
c.touchUpInsideCount -= 1
}
}
@objc private func eventHandler() {
_ = subscriber?.receive(control)
}
}
/// A custom `Publisher` to work with our custom `UIControlSubscription`.
public struct UIControlPublisher<Control: UIControl>: 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<S>(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<Self> {
return UIControlPublisher(control: self, events: events)
}
}