codecamp

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 代码应该很简单,有疑问的欢迎联系我,一起探讨~

温馨提示
下载编程狮App,免费阅读超1000+编程语言教程
取消
确定
目录

关闭

MIP.setData({ 'pageTheme' : getCookie('pageTheme') || {'day':true, 'night':false}, 'pageFontSize' : getCookie('pageFontSize') || 20 }); MIP.watch('pageTheme', function(newValue){ setCookie('pageTheme', JSON.stringify(newValue)) }); MIP.watch('pageFontSize', function(newValue){ setCookie('pageFontSize', newValue) }); function setCookie(name, value){ var days = 1; var exp = new Date(); exp.setTime(exp.getTime() + days*24*60*60*1000); document.cookie = name + '=' + value + ';expires=' + exp.toUTCString(); } function getCookie(name){ var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)'); return document.cookie.match(reg) ? JSON.parse(document.cookie.match(reg)[2]) : null; }