運(yùn)用runtime機(jī)制,防止按鈕多次點(diǎn)擊

? ? 在開發(fā)的實(shí)際過程中,我們會(huì)發(fā)現(xiàn)UIButton的觸發(fā),可能會(huì)因?yàn)橛脩舻母咚龠B續(xù)點(diǎn)擊而被觸發(fā)多次。在實(shí)際的場景化服務(wù)中,肯能這并不是我們想要的。我們更傾向于給按鈕設(shè)置一個(gè)響應(yīng)間隔時(shí)間。由此引發(fā)了,下列的思考。

1、改變button的enable狀態(tài),再點(diǎn)擊后的一段時(shí)間內(nèi)置為NO;

-(void)buttonClick:(UIButton *)btn

{

? ? self.btn.enabled = NO;

? ? [btn performSelector:@selector(changeBtnEnable) withObject:nil afterDelay:1.0f];

}

- (void)changeBtnEnable

{

? ? self.btn.enable = YES;

}

2、鑒于第一種方法過于繁瑣,且每個(gè)button都要重復(fù)設(shè)置,所以摒棄這種做法。直接寫一個(gè)UIButtonde分類。

.h文件

#import <objc/runtime.h>//倒入runtime

@interface UIButton (NoClickTwo)

@property (nonatomic , assign) NSTimeInterval timeInterval;

@property (nonatomic , assign) BOOL? ? isIgnoreEvent;//YES不允許點(diǎn)擊NO允許點(diǎn)擊

@end

.m文件實(shí)現(xiàn)

@implementation UIButton (NoClickTwo)

- (NSTimeInterval)timeInterval

{


? ? return [objc_getAssociatedObject(self, _cmd) doubleValue];

}

- (void)setTimeInterval:(NSTimeInterval)timeInterval

{

? ? objc_setAssociatedObject(self, @selector(timeInterval), @(timeInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);

}

//runtime動(dòng)態(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的實(shí)現(xiàn)添加到系統(tǒng)方法中

? ? ? ? *也就是說將methodA方法指針添加成方法methodB

? ? ? ? *返回值表示是否添加成功

? ? ? ? */

? ? ? ? BOOL isAdd = class_addMethod(self, selA, method_getImplementation(methodB), method_getTypeEncoding(methodB));

? ? ? ? //添加成功了說明本類中不存在methodB ,所以此時(shí)必須將方法b的實(shí)現(xiàn)指針換成方法A的,否則b方法將沒有實(shí)現(xiàn)

? ? ? ? if (isAdd) {

? ? ? ? ? ? class_replaceMethod(self, selB, method_getImplementation(methodA), method_getTypeEncoding(methodA));

? ? ? ? }else{

? ? ? ? ? ? //添加失敗了說明本類中有methodB的實(shí)現(xiàn),此時(shí)只需要將methodA和methodB的函數(shù)指針互換一下即可。

? ? ? ? ? ? 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? 1.0f:self.timeInterval;

? ? ? ? if (self.isIgnoreEvent) {

? ? ? ? ? ? return;

? ? ? ? }else if(self.timeInterval > 0 ){

? ? ? ? ? ? [self performSelector:@selector(resetState)

? ? ? ? ? ? ? ? ? ? ? withObject:nil

? ? ? ? ? ? ? ? ? ? ? afterDelay:self.timeInterval];

? ? ? ? }

? ? }

? ? self.isIgnoreEvent = YES;

? ? //此處methodA和methodB方法IMP互換了,實(shí)際上執(zhí)行sendAction;所以不會(huì)死循環(huán)

? ? [self mySendAction:action to:target forEvent:event];

}

@end

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容