iOS防止重复点击Tips
实际开发中,我们经常会遇到需要给UIView加入单击点击事件,通常我们会这样做。
// 常规写法,会出现重复点击的误操作 let normalView = UILabel(frame: CGRect(x: (self.view.frame.width - 200) / 2, y: 100, width: 200, height: 48)) normalView.text = "Normal_Click" normalView.textAlignment = .center normalView.backgroundColor = UIColor.lightGray self.view.addSubview(normalView) // 下面开始 加入点击事件
normalView.isUserInteractionEnabled = true
let tapGestureRecognizer = UITapGestureRecognizer.init(target: self, action: #selector(ViewController.tapNormalView(targetView:)))
normalView.addGestureRecognizer(tapGestureRecognizer)
@objc func tapNormalView(targetView:UIView){ print("点击Normal_Label") }
以上的写法相对繁琐,但是还可以接受。但是很多情况下,用户可能会在极短的时间内重复点击按钮,导致事件被触发两次,造成业务的不完整性,所以上述代码我们可以这样改。 // 常规写法,去除重复点击,但是实现相当繁琐 let normalSingleView = UILabel(frame: CGRect(x: (self.view.frame.width - 200) / 2, y: 180, width: 200, height: 48)) normalSingleView.text = "Normal_SingleClick" normalSingleView.textAlignment = .center normalSingleView.backgroundColor = UIColor.lightGray self.view.addSubview(normalSingleView) // 下面开始 加入点击事件 normalSingleView.isUserInteractionEnabled = true let singleTapGestureRecognizer = UITapGestureRecognizer.init(target: self, action: #selector(ViewController.tapNormalView_SingleClick(targetView:))) normalSingleView.addGestureRecognizer(singleTapGestureRecognizer)
private var _normalInterf:TimeInterval = 0.6 private var _oldTime:TimeInterval = 0
@objc func tapNormalView_SingleClick(targetView:UIView){ let currentTime = CACurrentMediaTime() guard currentTime - _oldTime > _normalInterf else { // 如果两次点击间隔不长于 定义的间隔时间,该事件不响应 return } _oldTime = currentTime // 响应事件 print("点击Normal_SingleClick") } 以上代码实现了屏蔽极短时间内的再次点击逻辑,但是代码繁杂度极度上升。如果我们把这部分的功能代码抽取为一个父类也是可以的,但是会存在一个很大的缺陷,所有定制化的控件将不被支持,因为它们需要继承于我们抽取的父类,耦合性太高,修改难度非常大。 目前基于swift强大的扩展功能,这部分的功能代码,可以抽取一个公用的扩展方法出来,上述代码可以改写为如下: // 扩展进阶写法 let singleClickView = UILabel(frame: CGRect(x: (self.view.frame.width - 200) / 2, y: 260, width: 200, height: 48)) singleClickView.text = "Extension_SingleClick" singleClickView.textAlignment = .center singleClickView.backgroundColor = UIColor.lightGray self.view.addSubview(singleClickView) // 加入点击事件 , fixSingleClickListener 为 UIView 扩展方法。 singleClickView.fixSingleClickListener(0.6) { print("点击Extension_SingleClick") } 整体代码非常简单,只是一个思路的转变 import UIKit import ObjectiveC
private let DEFAULT_INTERF:TimeInterval = 0.6
private var view_oldTimeTag:UInt8 = 0 private var view_interfTag:UInt8 = 2 private var view_hasAddTargetTag:UInt8 = 3 private var view_singleClickTag:UInt8 = 4
extension UIView {
private var _ViewOldTime:TimeInterval {
get{
if let oldTime = objc_getAssociatedObject(self, &view_oldTimeTag) as? TimeInterval {
return oldTime
}
return 0
}
set(newValue){
objc_setAssociatedObject(self, &view_oldTimeTag, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
}
}
private var _Viewinterf:TimeInterval {
get{
if let interf = objc_getAssociatedObject(self, &view_interfTag) as? TimeInterval {
return interf
}
return DEFAULT_INTERF
}
set(newValue){
objc_setAssociatedObject(self, &view_interfTag, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
}
}
private var _ViewhasAddTarget:Bool {
get{
if let hasTargetFlag = objc_getAssociatedObject(self, &view_hasAddTargetTag) as? Bool {
return hasTargetFlag
}
return false
}
set(newValue){
objc_setAssociatedObject(self, &view_hasAddTargetTag, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
}
}
private var _ViewsingleClick:TXClickListener? {
get{
return objc_getAssociatedObject(self, &view_singleClickTag) as? TXClickListener
}
set(newValue){
if !self._ViewhasAddTarget {
self.isUserInteractionEnabled = true
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(UIView.tapGesture))
self.addGestureRecognizer(tapGesture)
self._ViewhasAddTarget = true
}
objc_setAssociatedObject(self, &view_singleClickTag, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
}
}
@objc fileprivate func tapGesture(){ let currentTime = CACurrentMediaTime() if (currentTime - self._ViewOldTime > _Viewinterf) { _ViewsingleClick?._singleClick?() _ViewOldTime = currentTime } }
func fixSingleClickListener( interf: TimeInterval = 0.6, listener: @escaping ()->()) { self._Viewinterf = interf self._ViewsingleClick = TXClickListener.init(block: listener) }
}
fileprivate class TXClickListener:NSObject {
var _singleClick:(()->Void)? = nil
init(block:@escaping (()->Void)) { self._singleClick = block }
} 这个Tips的开源地址是:https://github.com/TaurusXi/SingleClick 代码应该很简单,有疑问的欢迎联系我,一起探讨~