利用runtime解决UIButton 重复点击问题

UIControl的sendAction:to:forEvent:方法用于处理事件响应.如果我们在该方法的实现中, 添加针对点击事件的时间间隔相关的处理代码, 则能够做到在指定时间间隔中防止重复点击.

a、创建UIButton的分类MultiClick

    @interface UIButton (MultiClick)
    @property (nonatomic, assign) NSTimeInterval acceptEventInterval; // 重复点击的间隔
    @property (nonatomic, assign) NSTimeInterval acceptEventTime;
    @end

b、在分类中实现

    #import "UIButton+MultiClick.h"
    #import 
    @implementation UIButton (MultiClick)

    // 因category不能添加属性,只能通过关联对象的方式。
    static const char *UIControl_acceptEventInterval = "UIControl_acceptEventInterval";
    - (NSTimeInterval)acceptEventInterval {
        return  [objc_getAssociatedObject(self, UIControl_acceptEventInterval) doubleValue];
    }
    - (void)setAcceptEventInterval:(NSTimeInterval)acceptEventInterval {
        objc_setAssociatedObject(self, UIControl_acceptEventInterval, @(acceptEventInterval),         OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    static const char *UIControl_acceptEventTime = "UIControl_acceptEventTime";
    - (NSTimeInterval)acceptEventTime {
        return  [objc_getAssociatedObject(self, UIControl_acceptEventTime) doubleValue];
    }
    - (void)setAcceptEventTime:(NSTimeInterval)acceptEventTime {
        objc_setAssociatedObject(self, UIControl_acceptEventTime, @(acceptEventTime), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }

    // 在load时执行
    + (void)load {
        Method before   = class_getInstanceMethod(self, @selector(sendAction:to:forEvent:));
        Method after    = class_getInstanceMethod(self, @selector(mb_sendAction:to:forEvent:));
        //调用时,两个方法交换
       method_exchangeImplementations(before, after);
    }
    - (void)mb_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event {
        if ([NSDate date].timeIntervalSince1970 - self.acceptEventTime < self.acceptEventInterval) {
            return;
        }
        if (self.acceptEventInterval > 0) {
            self.acceptEventTime = [NSDate date].timeIntervalSince1970;
        }
        [self mb_sendAction:action to:target forEvent:event];
    }
    @end

c、使用

        UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
        [self.view addSubview:btn];
        btn.frame = self.view.bounds;
        [btn addTarget:self action:@selector(btnClick) forControlEvents:UIControlEventTouchUpInside];
        btn.acceptEventInterval = 2;
        btn.acceptEventTime = 2;
      - (void)btnClick{
          NSLog(@"btnClick");
      }

有图有真相


利用runtime解决UIButton 重复点击问题_第1张图片
image.png

注意:

因为在UIButton+QiEventInterval.m中的+load方法中交换了UIControl的sendAction:to:forEvent:方法,所以在使用UIControl或其子类(比如UISlider)的sendAction:to:forEvent:方法时会引起参数缺失的崩溃。可以将UIButton+MultiClick改成UIControl+MultiClick以避免此问题。

你可能感兴趣的:(利用runtime解决UIButton 重复点击问题)