231 lines
7.3 KiB
Swift
231 lines
7.3 KiB
Swift
//
|
||
// 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)
|
||
}
|
||
}
|