iOS-UIButton防止连续点击(点击抖动)
UIButton是我们iOS开发中常用的控件,连续/抖动点击也是用户使用中常发生的 !项目之后发现网上解决这一体验问题的资料还是蛮多的,但还是要自己做份笔记,方便下次查阅!
方案一:
- (void)viewDidLoad{ [super viewDidLoad]; // 1. 创建 btn 并添加点击事件 UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom]; [btn setFrame:CGRectMake(100, 100, 100, 60)]; btn.backgroundColor = [UIColor greenColor]; [btn addTarget:self action:@selector(clickbtn:) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:btn]; }
// 2. 延时时间设置为 t (此处设置为1.0s) ,所以凡是前后两次点击时间间隔不超过1.0s都会被取消 - (void)clickbtn:(UIButton *)btn{ NSLog(@" %s ",__FUNCTION__); [[self class] cancelPreviousPerformRequestsWithTarget:self selector:@selector(handleEvent:) object:btn]; [self performSelector:@selector(handleEvent:) withObject:btn afterDelay:1.0]; } // 3. 点击事件的处理方法 - (void)handleEvent:(UIButton *)btn{ NSLog(@" %s ",__FUNCTION__); }
方案二:给 UIButton 添加分类 ,方便项目中所有的 UIButton 实例都可以方便使用!
主要代码:
// .h 文件 #import <UIKit/UIKit.h> @interface UIButton (ClickEventTime) @property (nonatomic,assign) NSTimeInterval custom_acceptEventInterval; @end
// .m 文件 #import "UIButton+ClickEventTime.h" #import <objc/runtime.h> @implementation UIButton (ClickEventTime) /** 1. 拦截系统方法 2. 用自定义的方法替换第一步拦截的系统方法 3. 在自定义方法里尝试终止对连续点击的前面几次的响应 */ #pragma mark ----- 拦截系统方法 +(void)load{ SEL sysSEL = @selector(sendAction:to:forEvent:); Method systemMethod = class_getInstanceMethod(self, sysSEL); SEL customSEL = @selector(custom_sendAction:to:forEvent:); Method customMethod = class_getInstanceMethod(self, customSEL); method_exchangeImplementations(systemMethod, customMethod); } #pragma mark ----- 用于替换系统方法的自定义方法 - (void)custom_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event{ // 是否小于设定的时间间隔 BOOL needSendAction = (NSDate.date.timeIntervalSince1970 - self.custom_acceptEventTime >= self.custom_acceptEventInterval); // 更新上一次点击时间戳 if (self.custom_acceptEventInterval > 0) { self.custom_acceptEventTime = NSDate.date.timeIntervalSince1970; } if (needSendAction) { // 两次点击的时间间隔小于设定的时间间隔时,才执行响应事件 [self custom_sendAction:action to:target forEvent:event]; }else{ return; } } - (NSTimeInterval )custom_acceptEventTime{ return [objc_getAssociatedObject(self, "UIControl_acceptEventTime") doubleValue]; } - (void)setCustom_acceptEventTime:(NSTimeInterval)custom_acceptEventTime{ objc_setAssociatedObject(self, "UIControl_acceptEventTime", @(custom_acceptEventTime), OBJC_ASSOCIATION_RETAIN_NONATOMIC); } #pragma mark ------ 关联 - (NSTimeInterval )custom_acceptEventInterval{ return [objc_getAssociatedObject(self, "UIControl_acceptEventInterval") doubleValue]; } - (void)setCustom_acceptEventInterval:(NSTimeInterval)custom_acceptEventInterval{ objc_setAssociatedObject(self, "UIControl_acceptEventInterval", @(custom_acceptEventInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC); } @end