jsdw_ios/QuickLocation/Core/Extension/ControlEvents+Block.swift

231 lines
7.3 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// 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"
}
/// UIViewTap
/// - Parameters:
/// - taget: Any
/// - action: Selector
public func addTapGestrue(with taget: Any, action: Selector?) {
let tap = UITapGestureRecognizer(target: taget, action: action)
isUserInteractionEnabled = true
addGestureRecognizer(tap)
}
/// UIViewTap
/// - 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)
}
}
/// blockControlEvents
/// - 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)
}
/// identifierBlock
/// - 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)
}
}