87 lines
3.1 KiB
Swift
87 lines
3.1 KiB
Swift
|
|
//
|
|||
|
|
// UIButtonExt.swift
|
|||
|
|
// Crush
|
|||
|
|
//
|
|||
|
|
// Created by Leon on 2025/7/18.
|
|||
|
|
//
|
|||
|
|
|
|||
|
|
extension UIButton {
|
|||
|
|
// 使用 associated object 存储点击范围的内边距
|
|||
|
|
private struct AssociatedKeys {
|
|||
|
|
static var touchAreaInsets = "touchAreaInsets"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 可动态设置的点击范围内边距
|
|||
|
|
@objc var touchAreaInsets: UIEdgeInsets {
|
|||
|
|
get {
|
|||
|
|
return objc_getAssociatedObject(self, &AssociatedKeys.touchAreaInsets) as? UIEdgeInsets ?? .zero
|
|||
|
|
}
|
|||
|
|
set {
|
|||
|
|
objc_setAssociatedObject(self, &AssociatedKeys.touchAreaInsets, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 重写 point(inside:with:) 方法,扩展点击范围
|
|||
|
|
override open func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
|
|||
|
|
let insets = touchAreaInsets
|
|||
|
|
// 扩展后的点击区域
|
|||
|
|
let extendedBounds = bounds.inset(by: UIEdgeInsets(
|
|||
|
|
top: -insets.top,
|
|||
|
|
left: -insets.left,
|
|||
|
|
bottom: -insets.bottom,
|
|||
|
|
right: -insets.right
|
|||
|
|
))
|
|||
|
|
return extendedBounds.contains(point)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 全局防抖影响一些基本的barButton的点击事件,和一些三方库冲突
|
|||
|
|
//import ObjectiveC.runtime
|
|||
|
|
//
|
|||
|
|
//extension UIControl {
|
|||
|
|
// private struct AssociatedKeys {
|
|||
|
|
// static var ignoreEvent = 0
|
|||
|
|
// static var clickInterval = 0
|
|||
|
|
// }
|
|||
|
|
//
|
|||
|
|
// /// 是否正在忽略点击事件
|
|||
|
|
// private var isIgnoringEvent: Bool {
|
|||
|
|
// get { (objc_getAssociatedObject(self, &AssociatedKeys.ignoreEvent) as? Bool) ?? false }
|
|||
|
|
// set { objc_setAssociatedObject(self, &AssociatedKeys.ignoreEvent, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) }
|
|||
|
|
// }
|
|||
|
|
//
|
|||
|
|
// /// 点击间隔,默认 0.8 秒
|
|||
|
|
// var clickInterval: TimeInterval {
|
|||
|
|
// get { (objc_getAssociatedObject(self, &AssociatedKeys.clickInterval) as? TimeInterval) ?? 0.8 }
|
|||
|
|
// set { objc_setAssociatedObject(self, &AssociatedKeys.clickInterval, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) }
|
|||
|
|
// }
|
|||
|
|
//
|
|||
|
|
// // MARK: - 启用防抖(全局一次即可)
|
|||
|
|
// public static func enableClickDebounce() {
|
|||
|
|
// let originalSelector = #selector(UIControl.sendAction(_:to:for:))
|
|||
|
|
// let swizzledSelector = #selector(UIControl.swizzled_sendAction(_:to:for:))
|
|||
|
|
//
|
|||
|
|
// guard let originalMethod = class_getInstanceMethod(UIControl.self, originalSelector),
|
|||
|
|
// let swizzledMethod = class_getInstanceMethod(UIControl.self, swizzledSelector) else {
|
|||
|
|
// return
|
|||
|
|
// }
|
|||
|
|
// method_exchangeImplementations(originalMethod, swizzledMethod)
|
|||
|
|
// }
|
|||
|
|
//
|
|||
|
|
// @objc private func swizzled_sendAction(_ action: Selector, to target: Any?, for event: UIEvent?) {
|
|||
|
|
// if isIgnoringEvent {
|
|||
|
|
// return
|
|||
|
|
// }
|
|||
|
|
//
|
|||
|
|
// if clickInterval > 0 {
|
|||
|
|
// isIgnoringEvent = true
|
|||
|
|
// DispatchQueue.main.asyncAfter(deadline: .now() + clickInterval) { [weak self] in
|
|||
|
|
// self?.isIgnoringEvent = false
|
|||
|
|
// }
|
|||
|
|
// }
|
|||
|
|
//
|
|||
|
|
// // 调用原始实现
|
|||
|
|
// swizzled_sendAction(action, to: target, for: event)
|
|||
|
|
// }
|
|||
|
|
//}
|