最近測(cè)試?yán)吓苓^來提bug蔚袍,說按鈕可以點(diǎn)好幾次,然后蹦出來好幾個(gè)一樣的界面出來配名,解決了一個(gè)地方啤咽,其他地方也會(huì)冒出一樣的問題來晋辆,仔細(xì)一想,還是要從根本上解決問題闰蚕,于是想了幾個(gè)方法:
<br / >
1.添加UIButton分類栈拖,重寫-(BOOL)isTouchInside
方法,讓按鈕在點(diǎn)擊了一次之后的0.2s(可設(shè)置)
之內(nèi)變成不可點(diǎn)擊狀態(tài)
#import "UIButton+BK.h"
@implementation UIButton (BK)
-(BOOL)isTouchInside
{
self.enabled = NO;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
self.enabled = YES;
});
return YES;
}
@end
這種做法很簡單粗暴没陡,而且親測(cè)有效涩哟,唯一的缺點(diǎn)就是在按鈕點(diǎn)擊之后的0.2s內(nèi)按鈕狀態(tài)是不可點(diǎn)擊狀態(tài)的(灰色),雖說0.2s很短盼玄,但是追求極致體驗(yàn)的程序員肯定不會(huì)允許這種情況發(fā)生對(duì)吧 : ) 于是想到了另外一種方法
<br />
2.還是添加UIButton分類贴彼,利用runtime運(yùn)行時(shí)機(jī)制,讓按鈕點(diǎn)擊之后的短時(shí)間內(nèi)不再響應(yīng)此事件埃儿,廢話不多說器仗,show me the code
//
// UIButton+BK.h
// BMKP
//
// Created by 演員新之助 on 16/9/5.
// Copyright ? 2016年 Bmkp. All rights reserved.
//
#import <UIKit/UIKit.h>
#define defaultInterval 0.5//默認(rèn)時(shí)間間隔
@interface UIButton (BK)
@property(nonatomic,assign)NSTimeInterval timeInterval;//用這個(gè)給重復(fù)點(diǎn)擊加間隔
@property(nonatomic,assign)BOOL isIgnoreEvent;//YES不允許點(diǎn)擊NO允許點(diǎn)擊
@end
<br />
---------------------------我是可愛的分割線--------------------------
<br />
//
// UIButton+BK.m
// BMKP
//
// Created by 演員新之助 on 16/9/5.
// Copyright ? 2016年 Bmkp. All rights reserved.
//
#import "UIButton+BK.h"
@implementation UIButton (BK)
-(BOOL)isTouchInside
{
// self.enabled = NO;
// dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// self.enabled = YES;
// });
funclog
return YES;
}
- (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{
//注意BOOL類型需要用OBJC_ASSOCIATION_RETAIN_NONATOMIC不要用錯(cuò),否則set方法會(huì)賦值出錯(cuò)
objc_setAssociatedObject(self,@selector(isIgnoreEvent),@(isIgnoreEvent),OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (BOOL)isIgnoreEvent{
//_cmd == @select(isIgnore);和set方法里一致
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的IMP互換一下即可剃斧。
method_exchangeImplementations(methodA, methodB);
}
});
}
//當(dāng)我們按鈕點(diǎn)擊事件sendAction時(shí)將會(huì)執(zhí)行mySendAction
- (void)mySendAction:(SEL)action to:(id)target forEvent:(UIEvent*)event
{
if([self isKindOfClass:[UIButton class]]) {
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互換了轨香,實(shí)際上執(zhí)行sendAction;所以不會(huì)死循環(huán)
self.isIgnoreEvent=YES;
[self mySendAction:action to:target forEvent:event];
}
@end
這樣就完美解決的按鈕重復(fù)點(diǎn)擊的問題幼东,親測(cè)有效
<br />