UIButton防止重复点击

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

Leave a Reply

Required fields are marked *