防止UIButton重复点击,可能会调用多次SEL,所以可以为其增加一个时间间隔,去处理重复点击的逻辑事物。
首先聊聊UIButton,UIButton继承与UIControl,UIControl继承与UIView,UIView,继承与UIReponder,其中UIControl负责管理他的响应事件,UIView管理Button上的视图,UIReponder响应他的事件,所以要控制UIButton的多次点击,要冲UIControl下手。
@interface UIControl (Impose)
//点击间隔时间
@property (nonatomic,assign)double OperateInterval;
@end
//
#import "UIControl+Impose.h"
#import <objc/runtime.h>
@interface UIControl ()
//记录当前时间差是不是已经结束,再去执行
@property (nonatomic,assign)bool operateValid;
@end
@implementation UIControl (Impose)
+ (void)load
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class class = self.class;
//交换UIControl的sendAction:to:forEvent:方法,因为Button在addTarget的时候,
//给UIControl发送消息,让UIControl和UIResponder进行事件传递
SEL originalSelector = @selector(sendAction:to:forEvent:);
SEL swizzledSelector = @selector(AS_sendAction:to:forEvent:);
Method originalMethod = class_getInstanceMethod(class, originalSelector);
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
BOOL didAddMethod = class_addMethod(class,originalSelector,method_getImplementation(swizzledMethod),method_getTypeEncoding(swizzledMethod));
if (didAddMethod) {
class_replaceMethod(class,swizzledSelector,method_getImplementation(originalMethod),method_getTypeEncoding(originalMethod));
}else{
method_exchangeImplementations(originalMethod, swizzledMethod);
}
});
}
- (void)AS_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event
{
//首先判断当前点击后是否可以再去执行SEL
if(self.operateValid == NO){
//设置为YES,让其等待
self.operateValid = YES;
[self AS_sendAction:action to:target forEvent:event];
//时间等待接收后,修改operateValid为NO,让其可以再次执行
[self performSelector:@selector(setOperateValid:) withObject:@(NO) afterDelay:self.OperateInterval];
}else{
//如果还没到规定时间,则提示或者其他操作
NSLog(@"点击太快了");
}
}
//绑定成员变量
- (void)setOperateInterval:(double)OperateInterval
{
objc_setAssociatedObject(self, @selector(OperateInterval), @(OperateInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
//获取绑定的成员变量
- (NSTimeInterval)OperateInterval
{
return [objc_getAssociatedObject(self, @selector(OperateInterval)) doubleValue];
}
- (void)setOperateValid:(bool)operateValid
{
objc_setAssociatedObject(self, @selector(operateValid),@(operateValid),OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (bool)operateValid
{
return [objc_getAssociatedObject(self, @selector(operateValid)) boolValue];
}
@end
Button在addTarget的时候,给UIControl发送消息,让UIControl和UIResponder进行事件传递,所以send后,会将事件传递给UIResponder,需要重写这个方法,内部进行拦截。

