解决办法
1.在每次点击时先取消之前的操作
- (void)cancelBtnAction:(UIButton *)btn {
[[self class] cancelPreviousPerformRequestsWithTarget:self selector:@selector(toDoSomething:) object: btn];
[self performSelector:@selector(toDoSomething:)withObject:btn afterDelay: 0.2f];
}
- (void)toDoSomething:(UIButton *)btn {
NSLog(@"在每次点击时先取消之前的操作");
}
2.点击一次后将button的enabled变为NO。在适当的地方把enabled变为YES
3.用Runtime监听点击事件,忽略重复点击,使其规定时间内只响应一次点击事件
- 为按钮添加多个target方法
//测试本方法之前记得把runtime注释打开
[testBtn setTitle:@"Runtime防止重复响应事件" forState:UIControlStateNormal];
[testBtn addTarget:self action:@selector(testBtn:) forControlEvents:UIControlEventTouchUpInside];
[testBtn addTarget:self action:@selector(testBtnTouchDown:) forControlEvents:UIControlEventTouchDown];
[testBtn addTarget:self action:@selector(testBtnTouchUpOutside:) forControlEvents:UIControlEventTouchUpOutside];
testBtn.eventTimeInterval = 2;
解释一下为什么要添加多个target:如果我们不区分target触发的方法,那么一个按钮同时设置多个target,就会出现_wxd_sendAction:to:forEvent:event执行多次,只而触发了一个target,具体触发的是哪个自己试验
- 在UIButton类目中加入属性
@interface UIButton (Leon)
// 为按钮添加点击间隔 eventTimeInterval秒
@property (nonatomic, assign) NSTimeInterval eventTimeInterval;
@end
@interface UIButton ()
/*
***key:方法的名字
***value:是否在eventTimeInterval秒内重复点击
***问题描述:如果按钮只增加了一个addTarget:action:forControlEvents:网络上的实现方案是没有问题的,如果一个按钮btn增加多个addTarget:action:forControlEvents:方法,则网络上那个就不能实现,这个我做了改版
***适用于:同一个按钮,增加了多个addTarget:action:forControlEvents:方法,方法名字必须不同(不然会出现bug)
***不完善处:如果能获得是哪种UIControlEvents点击事件,根据那个点击事件来作为ignoreEventDic字典的key才能准确防止同一个按钮,不同的点击事件,来达成防止重复点击的效果
*/
@property (nonatomic, strong) NSMutableDictionary *ignoreEventDic;
@end
- 然后进行方法的交换
+ (void)load {
// Method Swizzling
[self swizzleMethod:@selector(sendAction:to:forEvent:) withMethod:@selector(_wxd_sendAction:to:forEvent:) error:nil];
}
- (void)_wxd_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event {
if (!self.ignoreEventDic) {
self.ignoreEventDic = [NSMutableDictionary dictionaryWithCapacity:1];
}
self.eventTimeInterval = self.eventTimeInterval == 0 ? defaultInterval : self.eventTimeInterval;
if ([[self.ignoreEventDic objectForKey:NSStringFromSelector(action)] isEqualToString:@"1"]){
return;
} else if (self.eventTimeInterval > 0){
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(self.eventTimeInterval * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self.ignoreEventDic setObject:@"0" forKey:NSStringFromSelector(action)];
});
}
[self.ignoreEventDic setObject:@"1" forKey:NSStringFromSelector(action)];
// 这里看上去会陷入递归调用死循环,但在运行期此方法是和sendAction:to:forEvent:互换的,相当于执行sendAction:to:forEvent:方法,所以并不会陷入死循环。
[self _wxd_sendAction:action to:target forEvent:event];
}
文章是根据前人肩膀上完成,类似的文章很多,自己的总是显得更加完善
有什么不足之处麻烦留言,必改.
网友评论