簡介
對于按鈕來說會存在多次點擊 當(dāng)程序卡住的時候 多次點擊按鈕會引起跳轉(zhuǎn)多次頁面、也獲取引起多次請求侵浸,在這里總結(jié)三種防止重復(fù)點擊的方法
第一種:每次在點擊時先取消之前的操作
- (void)buttonAction:(id)sender
{
[[self class] cancelPreviousPerformRequestsWithTarget:self selector:@selector(buttonAction:) object:sender];
[self performSelector:@selector(buttonAction:) withObject:sender afterDelay:0.2f];
}
第二種:點擊后設(shè)為不可被點擊的狀態(tài)戴卜,幾秒后恢復(fù):
-(void)buttonAction:(id)sender
{
self.button.enabled = NO;
[self performSelector:@selector(changeButtonStatus) withObject:sender afterDelay:1.0f];//防止重復(fù)點擊
}
-(void)changeButtonStatus
{
self.button.enabled = YES;
}
第三種:使用runtime刹碾,一勞永逸我這設(shè)的是0.5秒內(nèi)不會被重復(fù)點擊
1.導(dǎo)入#import <objc/runtime.h>(可以放在PCH文件里)
2.創(chuàng)建UIControl或UIButton的的分類故觅!
創(chuàng)建分類文件:
2.1 打開Xcode中厂庇,新建文件,選擇OC文件
2.2 在第二個界面输吏,F(xiàn)ile名為UIControl+ButtonCon.h权旷,將文件類型File Type選為Category類,在類里選繼承的類別贯溅,這里咱們選的Class是UIButton
注:若用UIButton分類拄氯,則會對對UIButton創(chuàng)建的按鈕反應(yīng)。
2.3 分類創(chuàng)建完畢對分類進(jìn)行操作
.h文件
#import <UIKit/UIKit.h>
#import <objc/runtime.h>
#define defaultInterval .5 //默認(rèn)時間間隔
@interface UIControl (ButtonCon)
@property(nonatomic,assign)NSTimeInterval timeInterval; //用這個給重復(fù)點擊加間隔
@property(nonatomic,assign)BOOL isIgnoreEvent; //YES不允許點擊NO允許點擊
@end
.m文件
#import "UIControl+ButtonCon.h"
@implementation UIControl (ButtonCon)
- (NSTimeInterval)timeInterval
{
return [objc_getAssociatedObject(self, _cmd) doubleValue];
}
- (void)setTimeInterval:(NSTimeInterval)timeInterval
{
objc_setAssociatedObject(self, @selector(timeInterval), @(timeInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
//runtime動態(tài)綁定屬性
- (void)setIsIgnoreEvent:(BOOL)isIgnoreEvent
{
objc_setAssociatedObject(self, @selector(isIgnoreEvent), @(isIgnoreEvent), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (BOOL)isIgnoreEvent
{
return [objc_getAssociatedObject(self, _cmd) boolValue];
}
- (void)resetState
{
[self setIsIgnoreEvent:NO];
}
+ (void)load
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
SEL selA = @selector(sendAction:to:forEvent:);
SEL selB = @selector(mySendAction:to:forEvent:);
Method methodA = class_getInstanceMethod(self, selA);
Method methodB = class_getInstanceMethod(self, selB);
//將methodB的實現(xiàn)添加到系統(tǒng)方法中也就是說將methodA方法指針添加成方法methodB的返回值表示是否添加成功
BOOL isAdd = class_addMethod(self, selA, method_getImplementation(methodB), method_getTypeEncoding(methodB));
//添加成功了說明本類中不存在methodB所以此時必須將方法b的實現(xiàn)指針換成方法A的它浅,否則b方法將沒有實現(xiàn)译柏。
if (isAdd) {
class_replaceMethod(self, selB, method_getImplementation(methodA), method_getTypeEncoding(methodA));
} else {
//添加失敗了說明本類中有methodB的實現(xiàn),此時只需要將methodA和methodB的IMP互換一下即可姐霍。
method_exchangeImplementations(methodA, methodB);
}
});
}
- (void)mySendAction:(SEL)action to:(id)target forEvent:(UIEvent*)event
{
if ([NSStringFromClass(self.class) isEqualToString:@"UIButton"]) {
self.timeInterval = self.timeInterval == 0 ? defaultInterval : self.timeInterval;
if (self.isIgnoreEvent) {
return;
} else if (self.timeInterval > 0) {
[self performSelector:@selector(resetState) withObject:nil afterDelay:self.timeInterval];
}
}
//此處methodA和methodB方法IMP互換了鄙麦,實際上執(zhí)行sendAction;所以不會死循環(huán)
self.isIgnoreEvent = YES;
[self mySendAction:action to:target forEvent:event];
}
@end
結(jié)束語
到這里就結(jié)束了镊折,如若不懂的話可以??留言胯府,也可以加入群討論
喜歡的話 記得關(guān)注、收藏恨胚、點贊喲