首先理解下几个概念
1、IMP:它是指向一个方法具体实现的指针,每一个方法都有一个对应的IMP,当你发起一个消息之后,最终它会执行的那段代码,就是由IMP这个函数指针指向了这个方法实现的
2、SEL:方法名称的描述,只记录方法的编号不记录具体的方法,具体的方法是 IMP
3、Method:是一个类实例,里面的结构体有一个方法选标 SEL – 表示该方法的名称,一个types – 表示该方法参数的类型,一个 IMP - 指向该方法的具体实现的函数指针。

针对UIButton、UISegmentedControl、UISwitch这些继承自UIControl的控件可通过hook sendAction:to:forEvent:这个方法实现控件的重复点击
具体思路:
1、创建UIButton的类别,使用runtime添加public属性eventInterval作为计时因子
2、添加private属性eventUnavailable来控制button的点击事件是否有效
3、在+load方法中实现系统sendAction:to:forEvent:方法与自定义方法进行交换
代码实现:

+ (void)load {static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{Method origMethod = class_getInstanceMethod([self class], @selector(sendAction:to:forEvent:));SEL origsel = @selector(sendAction:to:forEvent:);Method swizMethod = class_getInstanceMethod([self class], @selector(tk_sendAction:to:forEvent:));SEL swizsel = @selector(tk_sendAction:to:forEvent:);BOOL addMehtod = class_addMethod([self class], origsel, method_getImplementation(swizMethod), method_getTypeEncoding(swizMethod));if (addMehtod) {class_replaceMethod([self class], swizsel, method_getImplementation(origMethod), method_getTypeEncoding(origMethod));} else {method_exchangeImplementations(origMethod, swizMethod);}});
}- (void)tk_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event {if (self.eventUnavailable == NO) {self.eventUnavailable = YES;[self tk_sendAction:action to:target forEvent:event];[self performSelector:@selector(setEventUnavailable:) withObject:@(NO) afterDelay:self.eventInterval];}
}

针对单击事件可对UITapGestureRecognizer的initWithTarget:action:或addTarget:action:进行hook
具体思路:
1、创建UITapGestureRecognizer的类别,使用runtime添加public属性eventInterval作为计时因子
2、添加private属性eventUnavailable来控制button的点击事件是否有效
3、在+load方法中实现系统initWithTarget:action:方法与自定义方法进行交换
4、将target和selector关联到创建的类别中并且将selector替换成类别中自定义的响应方法
代码实现:

- (instancetype)initTKWithTarget:(id)target action:(SEL)action {self = [self initTKWithTarget:self action:@selector(tap:)];objc_setAssociatedObject(self, gestureTargetKey, target, OBJC_ASSOCIATION_RETAIN_NONATOMIC);objc_setAssociatedObject(self, gestureSelKey, NSStringFromSelector(action), OBJC_ASSOCIATION_RETAIN_NONATOMIC);return self;
}- (void)tap:(UIGestureRecognizer *)tapGesture {id target = objc_getAssociatedObject(self, gestureTargetKey);SEL action = NSSelectorFromString(objc_getAssociatedObject(self, gestureSelKey));if (self.eventUnavailable == NO) {self.eventUnavailable = YES;[target performSelector:action];[self performSelector:@selector(setEventUnavailable:) withObject:@(NO) afterDelay:self.eventInterval];}
}

针对单击事件的第二种实现方式实现带参数的init方法
具体思路:
1、在分类中实现initWithTarget:action:eventIntervl:的方法通过传进去计时因子控制点击事件是否可以响应,将手势的代理设置成新建的分类
2、添加属性eventUnavailable来控制点击事件是否有效
3、通过重写gestureRecognizer:shouldReceiveTouch:来控制点击事件是否响应
代码实现:

-(instancetype)initWithTarget:(id)target action:(SEL)action eventIntervl:(NSTimeInterval)eventIntervl {self = [super init];if (self) {self.eventInterval = eventIntervl;self.delegate = self;[self addTarget:target action:action];}return self;
}- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{if (self.eventUnavailable == NO) {self.eventUnavailable = YES;[self performSelector:@selector(setEventUnavailable:) withObject:@(NO) afterDelay:self.eventInterval];return YES;} else {return NO;}
}

UIButton防止按钮和手势的暴力点击相关推荐

  1. 按钮和手势无效问题及解决方案

    按钮和手势无效问题 一般有四种情况: 1.父类或本身userInteractionEnabled设置了NO.置正确userInteractionEnabled就可以. 2.被上层的组件的事件拦截.如上 ...

  2. php点击按钮变文字,点击按钮文字变成input框,点击保存变成文字的实现

    下面为大家带来一篇点击按钮文字变成input框,点击保存变成文字的实现代码.内容挺不错的,现在分享给大家,也给大家做个参考. 点击按钮文字变成input框,点击保存变成文字的实现代码 点击按钮文字变成 ...

  3. php如何模拟网页点击按钮,python模拟点击网页按钮如何实现 python模拟点击网页按钮实现方法...

    python模拟点击网页按钮如何实现 python模拟点击网页按钮实现方法 本篇文章小编给大家分享一下python模拟点击网页按钮实现方法,小编觉得挺不错的,现在分享给大家供大家参考,有需要的小伙伴们 ...

  4. pythontkinter使按钮失效_python2.7为什么点击了quot;开始quot;按钮后,tkinter上的按钮,图中红色部分,再也点不动了? - SegmentFault 思否...

    python2.7为什么点击了"开始"按钮后,tkinter上的按钮,图中红色部分,再也点不动了?如何能在点击"开始"按钮后,还能点击tkinter的最小化,最 ...

  5. 使用函数节流思想避免 SAP UI5 应用里按钮短时间内被高频重复点击试读版

    一套适合 SAP UI5 初学者循序渐进的学习教程 作者简介 Jerry Wang,2007 年从电子科技大学计算机专业硕士毕业后加入 SAP 成都研究院工作至今.Jerry 是 SAP 社区导师,S ...

  6. 点击按钮显示文字,再次点击隐藏文字

    点击按钮显示文字,再次点击隐藏文字 点击按钮显示文字,再次点击按钮隐藏文字 通过if条件判断css样式来做 <!DOCTYPE html> <html lang="en&q ...

  7. jq实现点击一个按钮,触发另一个点击事件(点击按钮触发另一个按钮的点击事件)

    jq实现点击一个按钮,触发另一个点击事件 $("#a").click(function(){$("#b").trigger('click');}) 实现点击完i ...

  8. html点击按钮文件上传,js点击按钮实现文件上传

    点击按钮实现文件上传 点击按钮实现文件上传 $('#uploadFileButton').click(function () { $('#upload').click(); }); $('#uploa ...

  9. 【Android】点击按钮播放音乐,再次点击停止播放

    1.在res下新建raw文件夹 将音频复制粘贴至文件夹 2.代码 (1)PlatformActivity.java public static int cnt = 0;SoundPool sp;//声 ...

最新文章

  1. Elasticsearch的javaAPI之query dsl-queries
  2. 足球预测_预测足球热
  3. CSS3 Transition介绍
  4. python oracle连接池_python - DBUtils 连接池减少oracle数据库的连接数
  5. Oracle数据库存储过程 ,去除给定字符串中重复的字符串
  6. 六个好用的程序员开发在线工具
  7. 小米一键上锁工具_便宜好用:小米智能门锁E 上手体验报告
  8. 写了一个个人资产管理的后台系统
  9. Excel从入门到精通--基础篇
  10. LOJ#515. 「LibreOJ β Round #2」贪心只能过样例(bitset)
  11. 拯救期末!大四留学生发“论文机器人”,替你读文献给方向调格式,已被ACL2019收录
  12. 在Python中用WordCloud生成聊天记录热点词汇词云图
  13. Incapsula到底是什么
  14. JVM 上篇(4):虚拟机栈
  15. imp导入时遇到的问题及解决方式
  16. 目前缺少用于语义分割的 3D LiDAR 数据吗?关于三维点云数据集和方法的调查
  17. 基于JAVA体育用品购物系统计算机毕业设计源码+系统+mysql数据库+lw文档+部署
  18. php圆的周长_php面向对象编程练习:计算矩形、三角形、圆形的周长和面积
  19. C语言,一个分号引发的问题:Run-Time Check Failure #2 - Stack around the variable ‘class1‘ was corrupted.
  20. Python中的时间戳具体是什么

热门文章

  1. C++拾趣——STL容器的插入、删除、遍历和查找操作性能对比(Windows VirtualStudio)——插入
  2. Python3中raise用法
  3. K-均值聚类(K-Means) C++代码实现
  4. C++/C++11中头文件functional的使用
  5. json11库的使用
  6. 【Qt】qss样式表之:自定义属性实现动态切换样式
  7. jpanel不使用jframe保存的图片为空_使用DataBinding还在为数据处理头疼?这篇文章帮你解决问题
  8. java ee 修改_java ee 在数据库中执行增删改查
  9. 争吵所达到的效果要_悟空:不要害怕争吵,有时候争吵一些不喜欢的事情也能创造和谐...
  10. hibernate 复合主键 根据主键删除_hibernate封装Utils工具类