// // Block.swift // DLSDK // // Created by osell on 2023/3/6. // import UIKit import ObjectiveC.runtime public typealias VoidAnyBlock = (Any) -> Void class InnerBlockTarget: NSObject { var identifier: String = "" var block: VoidAnyBlock? var events: UIControl.Event? override init() { self.identifier = UUID().uuidString super.init() } @objc func invoke(_ sender: Any) { if let block = block { block(sender) } } } // MARK: - UIGestureRecognizer + Block @objc extension UIGestureRecognizer { struct BlockKey { static var innerBlockTargets = "innerBlockTargets" } var innerBlockTargets: [InnerBlockTarget] { get { guard let targets = objc_getAssociatedObject(self, &BlockKey.innerBlockTargets) as? [InnerBlockTarget] else { return [] } return targets } set { objc_setAssociatedObject(self, &BlockKey.innerBlockTargets, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) } } /// 增加Tap /// - Parameter block: 事件回调 /// - Returns: UIGestureRecognizer @discardableResult public class func gestureRecognizer(with block: @escaping VoidAnyBlock) -> UIGestureRecognizer { let gestureRecognizer = UIGestureRecognizer() gestureRecognizer.addBlock(block) return gestureRecognizer } /// 增加Block @discardableResult public func addBlock(_ block: @escaping VoidAnyBlock) -> String { let target = InnerBlockTarget() target.block = block addTarget(target, action: #selector(InnerBlockTarget.invoke(_:))) var targets = innerBlockTargets targets.append(target) innerBlockTargets = targets return target.identifier } /// 删除Block public func removeBlock(identifier: String) { if identifier.isEmpty { return } var targets = innerBlockTargets guard let target = targets.first(where: { $0.identifier == identifier }) else { return } removeTarget(target, action: #selector(InnerBlockTarget.invoke(_:))) targets.removeObject(target) innerBlockTargets = targets } /// 删除全部 public func removeAll() { innerBlockTargets.forEach { self.removeTarget($0, action: #selector(InnerBlockTarget.invoke(_:))) } innerBlockTargets = [] } } // MARK: - UIView + Block @objc extension UIView { struct BlockKey { static var addTapGestrueBlock = "addTapGestrueBlock" } /// UIView添加Tap点击事件 /// - Parameters: /// - taget: Any /// - action: Selector public func addTapGestrue(with taget: Any, action: Selector?) { let tap = UITapGestureRecognizer(target: taget, action: action) isUserInteractionEnabled = true addGestureRecognizer(tap) } /// UIView添加Tap点击事件 /// - Parameter block: 点击Block回调 /// - Returns: indetifier @discardableResult public func addTapGestrue(block: @escaping VoidAnyBlock) -> String { let tap = UITapGestureRecognizer() let indetifier = tap.addBlock(block) objc_setAssociatedObject(tap, &BlockKey.addTapGestrueBlock, indetifier, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) isUserInteractionEnabled = true addGestureRecognizer(tap) return indetifier } /// 移除Tap事件 /// - Parameter identifier: identifier public func removeTapGestrueBlock(with identifier: String) { if identifier.isEmpty { return } gestureRecognizers?.forEach { if $0.isKind(of: UITapGestureRecognizer.self), let tempidentifier = objc_getAssociatedObject($0, &BlockKey.addTapGestrueBlock) as? String, tempidentifier == identifier { $0.removeBlock(identifier: identifier) self.removeGestureRecognizer($0) } } } } // MARK: - UIControl + Block @objc extension UIControl { struct BlockKey { static var innerBlockTargets = "innerBlockTargets" } var innerBlockTargets: [InnerBlockTarget] { get { guard let targets = objc_getAssociatedObject(self, &BlockKey.innerBlockTargets) as? [InnerBlockTarget] else { return [] } return targets } set { objc_setAssociatedObject(self, &BlockKey.innerBlockTargets, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) } } /// 添加block的ControlEvents /// - Parameters: /// - controlEvents: UIControl.Event /// - block: (Any) -> Void /// - Returns: identifier @discardableResult public func addBlock(for controlEvents: UIControl.Event, block: @escaping VoidAnyBlock) -> String { if let target = innerBlockTargets.first(where: { $0.events == controlEvents }) { innerBlockTargets.removeObject(target) } let target = InnerBlockTarget() target.block = block target.events = controlEvents addTarget(target, action: #selector(InnerBlockTarget.invoke(_:)), for: controlEvents) var targets = innerBlockTargets targets.append(target) innerBlockTargets = targets return target.identifier } /// 移除Block /// - Parameters: /// - controlEvents: UIControl.Event /// - identifier: identifier public func removeBlock(for controlEvents: UIControl.Event, identifier: String) { if identifier.isEmpty { return } removeAllBlock(for: controlEvents, identifier: identifier) } /// 移除identifier全部Block /// - Parameters: /// - controlEvents: UIControl.Event /// - identifier: identifier, 默认为空,会移除所有的block public func removeAllBlock(for controlEvents: UIControl.Event, identifier: String = "") { var targets = innerBlockTargets var removes = [InnerBlockTarget]() targets.forEach { if let events = $0.events, ((events.rawValue & controlEvents.rawValue) != 0), ($0.identifier == identifier || identifier.isEmpty) { let event = UIControl.Event(rawValue: events.rawValue & (~controlEvents.rawValue)) if event.rawValue != 0 { removeTarget($0, action: #selector(InnerBlockTarget.invoke(_:)), for: controlEvents) $0.events = event addTarget($0, action: #selector(InnerBlockTarget.invoke(_:)), for: event) } else { removeTarget($0, action: #selector(InnerBlockTarget.invoke(_:)), for: controlEvents) removes.append($0) } } } removes.forEach { targets.removeObject($0) } innerBlockTargets = targets } public func addTouchTarget(_ target: Any, action: Selector) { addTarget(target, action: action, for: .touchUpInside) } @discardableResult public func addTouchBlock(_ block: @escaping VoidAnyBlock) -> String { addBlock(for: .touchUpInside, block: block) } public func removeTouchBlock(with identifier: String) { removeBlock(for: .touchUpInside, identifier: identifier) } }