iOS开发基础136-防暴力点击
要在Objective-C中创建一个高度可复用的工具类,以防止按钮的暴力点击,并且使用切面编程(AOP)的方式,我们可以考虑使用Aspects这个库来实现方法的拦截。以下是具体的实现步骤:
第一步:引入Aspects库
首先,需要将Aspects集成到项目中。Aspects是一个轻量级的AOP框架,允许你在运行时拦截类的实例方法和类方法。你可以通过CocoaPods来添加此库:
pod 'Aspects'
第二步:创建UIButton的Category
接下来,创建一个UIButton的Category,用于添加防暴力点击的逻辑。
UIButton+PreventSpam.h:
#import <UIKit/UIKit.h>
@interface UIButton (PreventSpam)
// 设置间隔时间,进行防暴力点击设置
- (void)setPreventSpamInterval:(NSTimeInterval)interval;
@end
UIButton+PreventSpam.m:
#import "UIButton+PreventSpam.h"
#import <objc/runtime.h>
#import <Aspects/Aspects.h>
static const char *UIButton_preventSpamIntervalKey = "UIButton_preventSpamIntervalKey";
@implementation UIButton (PreventSpam)
- (void)setPreventSpamInterval:(NSTimeInterval)interval {
objc_setAssociatedObject(self, UIButton_preventSpamIntervalKey, @(interval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
// 使用Aspects进行方法拦截
[self aspect_hookSelector:@selector(sendAction:to:forEvent:) withOptions:AspectPositionInstead usingBlock:^(id<AspectInfo> aspectInfo, SEL action, id target, UIEvent *event) {
UIButton *button = aspectInfo.instance;
if (button.isIgnoring) {
return;
}
button.isIgnoring = YES;
// 执行原始的 sendAction:to:forEvent: 方法
// 这里直接调用原始方法是不合适的,因为这是一个拦截后的block,我们要重新invoke original invocation
[[aspectInfo originalInvocation] invoke];
// 延迟间隔时间后,重置为可以点击
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(interval * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
button.isIgnoring = NO;
});
} error:NULL];
}
// 判断当前是否应该忽略点击,通过关联对象添加属性
- (void)setIsIgnoring:(BOOL)isIgnoring {
objc_setAssociatedObject(self, @selector(isIgnoring), @(isIgnoring), OBJC_ASSOCIATION_ASSIGN);
}
- (BOOL)isIgnoring {
return [objc_getAssociatedObject(self, @selector(isIgnoring)) boolValue];
}
@end
使用
在适当的位置设置按钮的点击间隔:
#import "UIButton+PreventSpam.h"
[myButton setPreventSpamInterval:1.0]; // 点击间隔设置为1秒
注意
本示例使用了
Aspects库进行方法的拦截,这是一种运行时AOP的技巧。这里利用了Objective-C的动态特性。AOP可以帮助增加代码的可维护性和可复用性,但它也会增加代码的复杂性,使用时需要权衡。使用关联对象(
objc_setAssociatedObject和objc_getAssociatedObject)来给UIButton动态添加属性,用于存储是否应该忽略点击和间隔时间,这是Objective-C扩展现有类功能的常用技巧。在实际项目中,可能需要考虑多种情况和细节,如处理快速切换界面时按钮点击事件的响应等。
iOS开发基础136-防暴力点击的更多相关文章
- IOS开发基础知识碎片-导航
1:IOS开发基础知识--碎片1 a:NSString与NSInteger的互换 b:Objective-c中集合里面不能存放基础类型,比如int string float等,只能把它们转化成对象才可 ...
- IOS开发基础环境搭建
一.目的 本文的目的是windows下IOS开发基础环境搭建做了对应的介绍,大家可根据文档步骤进行mac环境部署: 二.安装虚拟机 下载虚拟机安装文件绿色版,点击如下文件安装 获取安装包: ...
- 【1】windows下IOS开发基础环境搭建
一.目的 本文的目的是windows下IOS开发基础环境搭建做了对应的介绍,大家可根据文档步骤进行mac环境部署: 二.安装虚拟机 下载虚拟机安装文件绿色版,点击如下文件安装 获取安装包: ...
- iOS开发——总结篇&IOS开发基础知识
IOS开发基础知识 1:Objective-C语法之动态类型(isKindOfClass, isMemberOfClass,id) 对象在运行时获取其类型的能力称为内省.内省可以有多种方法实现. 判断 ...
- iOS开发基础-九宫格坐标(6)
继续对iOS开发基础-九宫格坐标(5)中的代码进行优化. 优化思路:把字典转模型部分的数据处理操作也拿到模型类中去实现,即将 ViewController 类实现中 apps 方法搬到 WJQAppI ...
- iOS开发基础-九宫格坐标(5)
继续在iOS开发基础-九宫格坐标(4)的基础上进行优化. 一.改进思路 1)iOS开发基础-九宫格坐标(4)中 viewDidLoad 方法中的第21.22行对控件属性的设置能否拿到视图类 WJQAp ...
- iOS开发基础-九宫格坐标(4)
对iOS开发基础-九宫格坐标(3)的代码进行进一步优化. 新建一个 UIView 的子类,并命名为 WJQAppView ,将 appxib.xib 中的 UIView 对象与新建的视图类进行关联. ...
- iOS开发基础-九宫格坐标(3)之Xib
延续iOS开发基础-九宫格坐标(2)的内容,对其进行部分修改. 本部分采用 Xib 文件来创建用于显示图片的 UIView 对象. 一.简单介绍 Xib 和 storyboard 的比较: 1) X ...
- iOS开发基础-九宫格坐标(2)之模型
在iOS开发基础-九宫格(1)中,属性变量 apps 是从plist文件中加载数据的,在 viewDidLoad 方法中的第20行.26行中,直接通过字典的键名来获取相应的信息,使得 ViewCont ...
- iOS开发基础-图片切换(4)之懒加载
延续:iOS开发基础-图片切换(3),对(3)里面的代码用懒加载进行改善. 一.懒加载基本内容 懒加载(延迟加载):即在需要的时候才加载,修改属性的 getter 方法. 注意:懒加载时一定要先判断该 ...
随机推荐
- MyBatis日志模块源码分析
MyBatis源码的logging包下是日志模块的相关实现,Mybatis日志模块通过适配器模式和代理模式优雅的实现了SQL日志的输出功能. 一. 适配器模式实现了MyBatis对第三方日志框架的适配 ...
- IDEA使用——生成超文本格式的(HTML)JavaDoc
概述 在大型项目中不免会有很多对外暴露的方法与接口,那我们就需要在类或者方法上面按照JavaDoc标准编写注释,就比如这样: 前面我们也提到过在Idea中可以将鼠标停留在方法名上,然后点击F2查看方法 ...
- BGP中next-hop-self 小实验
next-hop-self 在EBGP和IBGP边界使用,对ibgp下一跳邻居使用 配置命令 router bgp 1234 neighbor 2.2.2.2 next-hop-self 使用Next ...
- 使用Wesky.Net.Opentools库,一行代码实现自动解析实体类summary注释信息(可用于数据实体文档的快速实现)
使用前,需要对你的项目勾选输出api文档文件. 引用Wesky.Net.OpenTools包,保持1.0.11版本或以上. 为了方便,我直接在昨天的演示基础上,继续给实体类添加注释. 昨天的演示文 ...
- react生命周期比较常用的几个
import React, { Component } from 'react' // 只有在类组件中才有生命周期 export default class App extends Component ...
- Nodejs fs模块 全局变量
fs模块提供了用于与文件进行交互相关方法 const fs = require('fs') # 写入数据 fs.writeFile(文件,数据,err=>{}) # 读取文件中数据 fs.rea ...
- Nodejs概述 安装Nodejs os模块 path模块 url模块 querystring模块
一.Nodejs概述 介绍 相关网址: https://nodejs.org/zh-cn/ http://nodejs.cn/ Node.js 是一个开源与跨平台的JavaScript 运行时环境.它 ...
- [SWPUCTF 2021 新生赛]include
打开我们可以看到让我们传入一个file,会出现一串代码,我们去分析一下: 当看到ini_set("allow_url_include","on");设置为on, ...
- sse 与 编译器自动优化
direct x 形式的矩阵和向量计算代码在编译的时候是自动汇编为 sse汇编的 何时使用手写sse 指令呢,当你的应用程序需要写一些物理运算时候 可以使用自己编写的sse计算函数来为 3维运算加速 ...
- dubbo~全局异常拦截器的使用与设计缺陷~续
上一次的介绍,主要围绕如何统一去捕获异常,以及为每一种异常添加自己的Mapper实现,并且我们知道,当在ExceptionMapper中返回非200的Response,不支持application/j ...