在開發過程中應該都遇到這樣的問題,當重復點擊某個按鈕時造成了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
