问题描述
在点击一个UIButton时,需要触发一个事件去执行,但如果多次重复点击一个UIButton,会重复执行该事件,造成不必要的Bug。
解决方案
添加UIButton的Category,添加一个betweenInterval
属性,通过该属性设置所需的时间间隔,并重写sendAction:to:forEvent:
方法,通过runtime
实现该方法自定义,在自定义的方法中判断点击按钮的时间间隔是否符合要求,如果符合则执行一次该方法,如果不符合则什么都不做
代码实现
#import <UIKit/UIKit.h>
@interface UIButton (IVAdd)
/**
按钮连续点击有效时间间隔 默认值是 0s
*/
@property (nonatomic,assign) NSTimeInterval betweenInterval;
@end
#import "UIButton+IVAdd.h"
#import <objc/runtime.h>
static const void *kLastClickTime = &kLastClickTime;//记录上次点击的时间
static const void *kBetweenInterval = &kBetweenInterval; //记录时间间隔
@implementation UIButton (IVAdd)
+ (void)load{
//设置默认值
objc_setAssociatedObject(self, kLastClickTime, @(CFAbsoluteTimeGetCurrent()), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
Method originalMethod = class_getInstanceMethod(self, @selector(sendAction:to:forEvent:));
Method swizzleMethod = class_getInstanceMethod(self, @selector(iv_sendAction:to:forEvent:));
class_addMethod(self, @selector(sendAction:to:forEvent:), class_getMethodImplementation(self, @selector(sendAction:to:forEvent:)), method_getTypeEncoding(originalMethod));
class_addMethod(self,@selector(iv_sendAction:to:forEvent:) , class_getMethodImplementation(self, @selector(iv_sendAction:to:forEvent:)), method_getTypeEncoding(swizzleMethod));
method_exchangeImplementations(originalMethod, swizzleMethod);
}
- (void)setBetweenInterval:(NSTimeInterval)betweenInterval{
objc_setAssociatedObject(self, kBetweenInterval, @(betweenInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSTimeInterval )betweenInterval{
NSTimeInterval betweenInterval = [objc_getAssociatedObject(self, kBetweenInterval)doubleValue];
return MAX(0.0, betweenInterval);
}
- (void)iv_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event{
//设置的时间间隔为0,直接处理即可
if (self.betweenInterval <= 0) {
[self iv_sendAction:action to:target forEvent:event];
return;
}
CFAbsoluteTime currentTime = CFAbsoluteTimeGetCurrent();
CFAbsoluteTime lastClickTime = [self lastClickTime];
if ((currentTime - lastClickTime) < self.betweenInterval) {
//点击时间间隔小于设定的时间间隔 ,什么都不做
return;
}
[self setupLastClickTime];
[self iv_sendAction:action to:target forEvent:event];
}
- (void)sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event{
[self sendAction:action to:target forEvent:event];
}
#pragma mark - Private Methods
- (void)setupLastClickTime{
objc_setAssociatedObject(self, kLastClickTime, @(CFAbsoluteTimeGetCurrent()), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (CFAbsoluteTime)lastClickTime{
return [objc_getAssociatedObject(self, kLastClickTime) doubleValue];
}
@end
复制代码
使用方法
直接设置betweenInterval
属性即可。
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button addTarget:self action:@selector(buttonClick:) forControlEvents:UIControlEventTouchUpInside];
button.frame = CGRectMake(100, 100, 100, 40);
button.betweenInterval = 2.0;//设置时间间隔为2s
[self.view addSubview:button];
复制代码