發(fā)現(xiàn)問(wèn)題
雙十一將至,項(xiàng)目上遇到了個(gè)問(wèn)題。用戶(QA??)連續(xù)點(diǎn)擊去下單支付的時(shí)候,微信/支付寶可能會(huì)返回“重復(fù)訂單”的錯(cuò)誤信息(廢話你點(diǎn)這么多次能不重復(fù)么??),同理點(diǎn)擊按鈕多次push的情況也會(huì)出現(xiàn)。
解決思路
這個(gè)問(wèn)題主要因?yàn)閎utton被多次點(diǎn)擊,重復(fù)的響應(yīng)了點(diǎn)擊事件。
解決方案
通常是如何解決
一般做法是在按鈕點(diǎn)擊事件里設(shè)置這個(gè)按鈕不可點(diǎn)擊,適當(dāng)?shù)臅r(shí)間之后再設(shè)置回來(lái),或者在點(diǎn)擊事件最后設(shè)置可以點(diǎn)擊。下面是在響應(yīng)事件的方法內(nèi)禁止點(diǎn)擊的代碼。
- (IBAction)clickBtn1:(UIbutton *)sender
{
sender.enabled = NO;
doSomething
sender.enabled = YES;
}
如果想做N秒內(nèi)禁止點(diǎn)重復(fù)擊操作則需要用方法performSelector:withObject:afterDelay:如果想解決程序里所有重復(fù)點(diǎn)擊的方法,需要把每個(gè)按鈕都寫(xiě)一遍,這不扯淡么…

微笑再見(jiàn).png
漂亮的解決方法
UIbutton繼承自UIControl,可以給UIControl添加Category。
MasterDefaultRepeatEventInterval可以定制時(shí)間間隔。
#import <UIKit/UIKit.h>
static NSTimeInterval MasterDefaultRepeatEventInterval = 1.5;
@interface UIControl (Interval)
@property (nonatomic, assign) NSTimeInterval M_repeatEventInterval;
@end
這里用了單例的方法來(lái)替換。
#import "UIControl+Interval.h"
#import <objc/runtime.h>
@implementation UIControl (Interval)
- (NSTimeInterval)M_repeatEventInterval {
return [objc_getAssociatedObject(self, _cmd) doubleValue];
}
- (void)setM_repeatEventInterval:(NSTimeInterval)M_repeatEventInterval {
objc_setAssociatedObject(self, @selector(M_repeatEventInterval), @(M_repeatEventInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
+ (void)load{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class class = [self class];
SEL originalselector = @selector(sendAction:to:forEvent:);
SEL swizzledSelector = @selector(M_sendAction:to:forEvent:);
Method originalMethod = class_getInstanceMethod(class, @selector(sendAction:to:forEvent:));
Method swizzleMethod = class_getInstanceMethod(class, @selector(M_sendAction:to:forEvent:));
//添加方法 語(yǔ)法:BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types) 若添加成功則返回No
// cls:被添加方法的類 name:被添加方法方法名 imp:被添加方法的實(shí)現(xiàn)函數(shù) types:被添加方法的實(shí)現(xiàn)函數(shù)的返回值類型和參數(shù)類型的字符串
BOOL didAddMethod = class_addMethod(class, originalselector, method_getImplementation(swizzleMethod), method_getTypeEncoding(swizzleMethod));
if (didAddMethod) {
class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
}else{
method_exchangeImplementations(originalMethod, swizzleMethod);
}
});
}
- (void)M_sendAction:(SEL)action to:(nullable id)target forEvent:(nullable UIEvent *)event {
static BOOL ignoreEvent = NO;
if (self.M_repeatEventInterval > 0) {
if (ignoreEvent) {
return;
}else{
ignoreEvent = YES;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(self.M_repeatEventInterval * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
ignoreEvent = NO;
});
[self M_sendAction:action to:target forEvent:event];
}
}else {
[self M_sendAction:action to:target forEvent:event];
}
}
就這樣!很快,很棒,很優(yōu)雅。就這樣吧??

嗨呀,開(kāi)心.gif