今天在公司項目中遇到一個問題,一個網絡請求的按鈕,點擊以后我沒有禁用,用戶一直點擊,APP頻繁的請求同一個接口,而且無限彈窗。
解決歷程
1.寫一個按鈕的分類或者子類,在- (void)sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event
這個方法重寫點擊事件,做一個時間的延時判斷,缺點,你需要在所有的按鈕創(chuàng)建的地方用這個類去替換原來的UIButton,項目改動太大.
2.還有一種方法,就是利用運行時,通過iOS黑魔法-Method Swizzling寫按鈕的祖宗(UIControl)的分類,通過方法交換,實現(xiàn)限制按鈕被重復點擊.下面是實現(xiàn)過程
在.h中聲明一個屬性,用來設置按鈕延時的時間:
@property(nonatomic,assign)NSTimeIntervalclickDurationTime;
在.m文件中代碼如下
#import"UIControl+extension.h"
static const NSTimeIntervaldefaultDuration =1.0f;// 記錄是否忽略按鈕點擊事件踩娘,
默認第一次執(zhí)行事件
static BOOL _isIgnoreEvent = NO;
staticvoidresetState()
{_isIgnoreEvent=NO;}
@implementationUIControl(extension)
@dynamicclickDurationTime;
+ (void)load
{
SEL originSEL = @selector(sendAction:to:forEvent:);
SEL newSEL = @selector(new_sendAction:to:forEvent:);
Method originM = class_getInstanceMethod([selfclass], originSEL);
constchar *typeEncodinds = method_getTypeEncoding(originM);
Method newM = class_getInstanceMethod([selfclass], newSEL);
IMP newIMP = method_getImplementation(newM);
if(class_addMethod([selfclass], newSEL, newIMP, typeEncodinds))
{
class_replaceMethod([selfclass], originSEL, newIMP, typeEncodinds);
}
else
{
method_exchangeImplementations(originM, newM);
}
}
- (void)my_sendAction:(SEL)action to:(id)target forEvent:(UIEvent*)event {
UITabBarButtonNSLog(@"%@",NSStringFromClass([selfclass]));// 保險起見戚哎,判斷下Class類型
if([selfisKindOfClass:[UIButtonclass]])
{//1. 按鈕點擊間隔事件self.clickDurationTime =self.clickDurationTime ==0? defaultDuration :self.clickDurationTime;//2. 是否忽略按鈕點擊事件if(_isIgnoreEvent)
{
//2.1 忽略按鈕事件
return;
}
else if (self.clickDurationTime >0)
{
//2.2 不忽略按鈕事件
// 后續(xù)在間隔時間內直接忽略按鈕事件
_isIgnoreEvent =YES;// 間隔事件后硼端,執(zhí)行按鈕事件dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(self.clickDurationTime *NSEC_PER_SEC)), dispatch_get_main_queue(), ^{? ? ? ? ? ? resetState();? ? ? ? });
// 發(fā)送按鈕點擊消息
[selfmy_sendAction:action to:target forEvent:event];
}}
else
{
[selfmy_sendAction:action to:target forEvent:event];
}
}
#pragma mark - associate- (void)setClickDurationTime:(NSTimeInterval)clickDurationTime {objc_setAssociatedObject(self,@selector(clickDurationTime), @(clickDurationTime), OBJC_ASSOCIATION_RETAIN_NONATOMIC);}- (NSTimeInterval)clickDurationTime {
return [objc_getAssociatedObject(self,@selector(clickDurationTime)) doubleValue];
}
@end
這個demo里面的所有按鈕都做了防止連續(xù)點擊事件,你的項目如果想集成這個功能,只需要把demo中的UIControl+Extension的分類放到你的項目中,并在需要用的地方導入頭文件,也可以直接放在PCH文件中就OK了.