iOS 按钮连点问题
在开发过程中应该都遇到这样的问题,当重复点击某个按钮时造成了push多次,造成体验很差,特别是在需要进行网络请求,网速不好时,出现的几率很大。这里主要介绍两种处理方式。
1.点击一次后将button的可交互性变为NO
如果在button的点击事件中要做耗时操作,比如进行网路请求时,可以考虑在点击时将按钮的可交互性变为NO,
btn.userInteractionEnabled = NO
然后在网络请求结束后再将其可交互性变为YES即可。这样可以有效避免按钮重复点击造成的多次puch问题,处理简单,缺点为比较麻烦,每个地方都要写,如果不加注意便会漏掉恢复可交互性。
2.也就是网上最常用的解决方法,使用runtime控制button响应事件的时间间隔,使其规定时间内只响应一次点击事件。
代码如下:
button分类的.h文件
@interface UIButton (Category)
/** 按钮重复点击的时间间隔,以秒为单位 **/
@property NSTimeInterval repeatEventInterval;
@end
.m文件
#import <objc/message.h>
// 默认的按钮点击时间间隔
static const NSTimeInterval defaultDuration = 2.0f;
const char *repeatEventIntervalKey = "repeatEventIntervalKey";
const char *previousClickTimeKey = "previousClickTimeKey";
@implementation UIButton (Category)
+ (void)load {
// 交换方法实现
Method sendAction = class_getInstanceMethod([self class], @selector(sendAction:to:forEvent:));
Method xy_SendAction = class_getInstanceMethod([self class], @selector(xy_sendAction:to:forEvent:));
method_exchangeImplementations(sendAction, xy_SendAction);
}
// // 重写,为了防止在tabBarController下点击tabBarItem时报错
- (void)sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event {
[super sendAction:action to:target forEvent:event];
}
- (void)setRepeatEventInterval:(NSTimeInterval)repeatEventInterval {
objc_setAssociatedObject(self, repeatEventIntervalKey, @(repeatEventInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSTimeInterval)repeatEventInterval {
NSTimeInterval repeatEventIn = (NSTimeInterval)[objc_getAssociatedObject(self, repeatEventIntervalKey) doubleValue];
// 如果外界设置的重复点击的时间间隔大于0,就按照用户设置的去处理,如果用户设置的间隔时间小于或等于0,就按照无间隔处理
if (repeatEventIn > 0) {
return repeatEventIn;
}else
{
return defaultDuration;
}
return 0.0;
}
- (void)setPreviousClickTime:(NSTimeInterval)previousClickTime {
objc_setAssociatedObject(self, previousClickTimeKey, @(previousClickTime), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSTimeInterval)previousClickTime {
NSTimeInterval previousEventTime = [objc_getAssociatedObject(self, previousClickTimeKey) doubleValue];
if (previousEventTime != 0) {
return previousEventTime;
}
return 1.0;
}
- (void)xy_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event {
NSTimeInterval time = [[[NSDate alloc] init] timeIntervalSince1970];
if (time - self.previousClickTime < self.repeatEventInterval) {
return;
}
// 如果间隔时间大于0
if (self.repeatEventInterval > 0) {
self.previousClickTime = [[[NSDate alloc] init] timeIntervalSince1970];
}
// 已在load中与系统的sendAction:to:forEvent:方法交换方法实现,所以下面调用的还是系统的方法
[self xy_sendAction:action to:target forEvent:event];
}
@end
参考链接:https://www.jianshu.com/p/98367b4d9816