Created
July 28, 2020 14:45
-
-
Save DanielCardonaRojas/4389a0091e869874e440e9ab2639a359 to your computer and use it in GitHub Desktop.
Add closure targets to UIControl subclasses.
This file contains hidden or 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 UIKit | |
public typealias Action = (UIControl) -> Void | |
extension NSObject { | |
var uniqueId: String { | |
return String(describing: self) | |
} | |
} | |
private struct AssociatedKey { | |
static var key = "EZAction_TargetContainer" | |
} | |
// MARK: - EZAction | |
public protocol EZAction: class { | |
associatedtype EZActionHost: AnyObject | |
var targetContainer: TargetContainer<EZActionHost> { get } | |
} | |
extension EZAction { | |
public var targetContainer: TargetContainer<Self> { | |
get { | |
if let value = objc_getAssociatedObject(self, &AssociatedKey.key) as? TargetContainer<Self> { | |
return value | |
} | |
let value = TargetContainer(host: self) | |
objc_setAssociatedObject(self, &AssociatedKey.key, value, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) | |
return value | |
} | |
} | |
} | |
// MARK: TargetContainer | |
public class TargetContainer<Host: AnyObject>: NSObject { | |
public unowned let host: Host | |
public init(host: Host) { | |
self.host = host | |
} | |
// Keep all targets alive | |
public var targets = [String: NSObject]() | |
} | |
public extension TargetContainer where Host: UIControl { | |
func addAction(_ action: @escaping Action, for event: Host.Event) { | |
let target = UIControlTarget(host: host, action: action, event: event) | |
targets[target.uniqueId] = target | |
} | |
} | |
class UIControlTarget: NSObject { | |
var action: Action? | |
init(host: UIControl, action: @escaping Action, event: UIControl.Event) { | |
super.init() | |
self.action = action | |
host.addTarget(self, action: #selector(handleEvent), for: event) | |
} | |
// MARK: - Action | |
@objc func handleEvent(_ sender: UIControl) { | |
action?(sender) | |
} | |
} | |
// MARK: Extensions | |
extension NSObject: EZAction { } | |
extension EZAction where Self: UIControl { | |
public func on(_ event: Self.Event, action: @escaping Action) { | |
self.targetContainer.addAction(action, for: event) | |
} | |
public func on(_ event: Self.Event, action: @escaping () -> Void) { | |
self.targetContainer.addAction({ _ in action() }, for: event) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment