防止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,需要重写这个方法,内部进行拦截。