UIButton防止按钮和手势的暴力点击
首先理解下几个概念
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;}
}
相关文章:

使用Windows7上的VS Code打开远程机Ubuntu上的文件操作步骤
之前在https://blog.csdn.net/fengbingchun/article/details/118991855 中介绍过在Windows10通过VS Code打开Ubuntu 16.04上的文件或文件夹的操作步骤。Windows7上的操作与Windows10有所不同,这里记录下。 Visual Studio Code Remote - SSH扩展允许你在任何远程机器…
微众银行殷磊:AI+卫星,从上帝视角洞察资产管理|BDTC 2019
出品 | AI科技大本营(ID:rgznai100)12月5日-7日,2019中国大数据技术大会(BDTC)于北京隆重举办,大会已成功举办十二届,是大数据领域极具影响力的行业盛会。本届大会汇聚了学术界、企业界上千位知…

【二分答案】【最短路】bzoj1614 [Usaco2007 Jan]Telephone Lines架设电话线
对于二分出的答案x而言,验证答案等价于将所有边权>x的边赋成1,否则赋成0,然后判断从1到n的最短路是否<K。 #include<cstdio> #include<cstring> #include<queue> using namespace std; #define N 1001 #define M 100…

Python3中装饰器@typing.overload的使用
typing.py的源码在:https://github.com/python/cpython/blob/main/Lib/typing.py 。此模块为类型提示(Type Hints)提供运行时支持。这里介绍下typing.overload的使用,从python 3.5版本开始将Typing作为标准库引入。 python3中增加了Function Annotation(…
19年NAACL纪实:自然语言处理的实用性见解 | CSDN博文精选
作者 | Nikita Zhiltsov翻译 | 王威力校对 | 李海明本文为你概述处理不同NLP问题时的具有卓越性能的方法、技术和框架等。计算语言:人类语言技术学会北美分会2019年年会(North American Chapter of the Association for Computational Linguistics: Huma…

高并发场景下数据库的常见问题及解决方案
一、分库分表 (1)为什么要分库分表 随着系统访问量的增加,QPS越来越高,数据库磁盘容量不断增加,一般数据库服务器的QPS在800-1200的时候性能最佳,当超过2000的时候sql就会变得很慢并且很容易被请求打死&a…

典型用户 persona
persona 典型用户 1、姓名:王涛 2、年龄:22 3、收入:基本无收入 4、代表用户在市场上的比例和重要性:王涛为铁道学生。本软件的用户主要是学生和老师,尤其是广大的铁大学子,所以此典型用户的重要性不言而喻…

PyTorch中nn.Module类简介
torch.nn.Module类是所有神经网络模块(modules)的基类,它的实现在torch/nn/modules/module.py中。你的模型也应该继承这个类,主要重载__init__、forward和extra_repr函数。Modules还可以包含其它Modules,从而可以将它们嵌套在树结构中。 只要…

什么是三层交换机、网关、DNS、子网掩码、MAC地址
一、什么是vlan? 二、单臂路由与三层交换机 三、什么是网关 一、什么是网关 二、如何来理解网关 三、网关的ip地址 四、网关是如何实现通信? 五、什么是默认网关? 四、什么是DNS 五、MAC地址 六、子网掩码 很多朋友多次问到什么是网关、dns、子网掩码&…
20行代码发一篇NeurIPS:梯度共享已经不安全了
整理 | 夕颜,Jane出品 | AI科技大本营(ID:rgznai100)【导读】12 月 8 日-14 日,NeurIPS 2019 在加拿大温哥华举行,和往常一样,今年大会吸引了数万名专家参会,并展示了计算机领域的最新进展。其中…

关于页面打印window.print()的样式问题
当我们打印网页的时候。有时候会发现。打印出来的。跟网页上看到的样式的差别有点大。这其中可能有的问题是。样式问题。 当调用打印(window.print())方法时。打印机会在网页的样式中查找 media print{}的样式,并适应到要打印的网页中。 所以 如果要打印的页面符合看…

Python3中参数*args和**kwargs介绍
在Python中,我们可以使用两种特殊符号将可变数量的参数传递给函数:*args和**kwargs。你可以使用任何单词代替args和kwargs,但通常做法是使用args和kwargs。 *args允许函数接受任意数量的位置参数(positional arguments)。 **kwargs收集所有未…
4大主流CPU处理器技术架构,不知道就out了!
作者 | 王艺威责编 | 阿秃RISC(精简指令集计算机)是一种执行较少类型计算机指令的微处理器,起源于80年代的MIPS主机(即RISC机),RISC机中采用的微处理器统称RISC处理器。这样一来,它能够以更快的…

grunt-connect-proxy解决开发时跨域问题
最近的项目中前后端是完全分离开发的,前端用grunt管理项目。这样就会导致一个问题:开发时前端调用后台的接口时因为不在一个服务器,所以会出现跨域问题。但是也不能用JSONP或CROS方式实现真正的跨域,因为项目发布时其实是在同一个…
混合推荐系统就是多个推荐系统“大杂烩”吗?
作者丨gongyouliu编辑丨zandy【导读】在本篇文章中,我们会介绍混合推荐系统(Hybrid Recommender Systems),就是利用多种推荐算法配合起来做推荐,期望避免单个推荐算法存在的问题,最终获得比单个算法更好的推荐效果。本篇文章我们从…

Python3中collections.OrderedDict介绍
Python3中的collections模块实现了特定目标的容器,以提供Python标准内建容器dict、list、set和tuple的替代选择,包括namedtuple、deque、ChainMap、Counter、OrderedDict、defaultdict、UserDict、UserList、UserString。这里介绍下OrderedDictÿ…

汗!雅虎中国个人空间
今天发现雅虎中国有了个人空间,偷偷试了下,让人失望到极点,几乎没有什么特点,和MSN很相似,空间相册放着好好的Flickr不用,偏偏弄了个很垃圾的相册,还有整合能力也不行。都不知道del.icio.us和Fl…

关于v$process与v$session中process的理解
v$session有个process字段,V$PROCESS有个SPID字段,这两个字段是不是一个意思呢?是不是都代表会话的操作系统进程呢?官方文档上的解释:SPID VARCHAR2(12) Operating system process identifierPROCESS VARCHAR2…

Python3中lambda表达式介绍
Python3中的lambda表达式或lambda函数是匿名函数(anonymous function),意味着该函数没有名称。def关键字用于在Python3中创建一个普通函数,类似地,lambda关键字用于在Python3中创建匿名函数。 Python3 lambda函数语法: lambda pa…
6大理由,告诉你为什么这个大会你不能错过! | 文末有福利
作者 | Carol出品 | 区块链大本营(blockchain_camp)* 文末可参与活动赢赠票!如果说有一个什么领域,能让中科院、华为、腾讯、京东、360、微众银行的大咖汇聚在一起,那一定是——区块链。悄咪咪地给大家剧透一下&#x…

魔与道的反复较量 反垃圾邮件技术
反垃圾邮件武器库不同的反垃圾邮件产品采用的技术有所不同,但总体来说,不外乎以下几种技术,其中,针对垃圾邮件的核心技术有贝叶斯智能分析、垃圾邮件评分、垃圾邮件指纹识别。转载于:https://blog.51cto.com/aonlin/17074

在Centos 7下编译openwrt+njit-client
首先要有一个centos7 step1:更新系统的源: yum install update 但是发现官方的源好像被墙了,于是自己又去换源,找163的源换。具体的操作最后的链接。 可是换完源之后发现163的源只支持到centos6、、、、、、但是就泪崩了。于是又把源换了回来…

Python3中内置函数callable介绍
Python3中的内置函数callable接受一个对象参数,如果此对象参数看起来可调用,则callable函数返回True,否则返回False。如果返回True,则调用仍有可能失败;但如果返回False,则调用对象将永远不会成功。 类是可…

户外广告新创意
近来,各大城市纷纷加大了对户外广告的监管力度,部分城市甚至停止审批户外广告牌。这让户外广告运营者和广告发布商甚为头疼。 长期以来,户外广告牌扮演着截然相反的“双重角色”,在户外广告运营者和广告发布商眼中,“寸…
百度重新定义「智能屏」,瞄准10后
加入「公开课」交流群,获取更多学习资料、课程及热招岗位等信息记者 | 阿司匹林作为中国智能音箱主力推手中的一员,百度从 2017 年已经开始布局。根据数据机构Strategy Analytics发布智能音箱市场报告,2019年第三季度,百度旗下人工…

jQuery最简单的表单提交方式
第一步:绑定事件 常用的与ajax相关的事件参考如下: 1、$(selector).click(function) 2、$(selector).change(function) 3、$(selector).keyup(function) 4、$(selector).submit(function) 提交表单前&#…

Python3中typing模块介绍
typing.py的源码在:https://github.com/python/cpython/blob/main/Lib/typing.py。此模块为类型提示(Type Hints)提供运行时支持(This module provides runtime support for type hints)。从python 3.5版本开始将Typing作为标准库引入。 python3中增加了Function An…

显示所有文件和文件夹无论如何 无法被设置
问题:XP系统选显示所有文件和文件夹确定后没有任何反应再次打开文件夹选项里面仍是不显示隐藏的文件和文件夹 答案:在记事本粘贴下面文字,另存为所有文件, .reg 格式。成功的话图标变为绿色碎方块。在双击它。 Windows Registry E…
工作5年后才明白的道理:不起眼的技能中,藏着你的未来
编程圈儿一直都流传着一个调侃的段子:一流程序员靠数学二流靠算法三流靠逻辑四流靠SDK五流靠Google和StackOverFlow六流靠百度和自己琢磨低端的看高端的就是黑魔法!从过来人的角度看,这不仅仅是个段子,而是目前程序员的真实写照。…

Transform-style和Perspective属性
在《CSS3 Transform——transform-origin》一文中主要介绍了CSS3 Transform属性中的transform-origin属性的使用,其实在transform属性中,transform-origin属性仅是其中之一,要彻底理解transform属性,这是不够的,必须的…