思考
怎么通過留給外部一個(gè)簡(jiǎn)單的API去實(shí)現(xiàn)一個(gè)按鈕在一定時(shí)間間隔內(nèi)不論點(diǎn)擊多少次,只執(zhí)行一次脸哀?
例如杯瞻,實(shí)際開發(fā)中瓣戚,當(dāng)點(diǎn)擊按鈕進(jìn)行網(wǎng)絡(luò)請(qǐng)求的時(shí)候,在接收到響應(yīng)之前焦读,user可能會(huì)暴力點(diǎn)擊子库,如果單位時(shí)間內(nèi)不停的發(fā)送網(wǎng)絡(luò)請(qǐng)求,不僅耗性能矗晃,單位時(shí)間過后連續(xù)的響應(yīng)也會(huì)造成不良的用戶體驗(yàn)仑嗅。
大致步驟
1.首先給按鈕一個(gè)屬性,記錄目標(biāo)時(shí)間間隔(創(chuàng)建UIControl分類张症,通過添加關(guān)聯(lián)對(duì)象實(shí)現(xiàn))
2.使用runtime方法交換仓技,捕獲系統(tǒng)方法并交換(sendAction:To:ForEvent:)
3.自定義點(diǎn)擊事件(添加需要判斷時(shí)間間隔的邏輯)
具體實(shí)現(xiàn)
給UIButton添加RespondOnce分類
@interface UIButton (RespondOnce)
/// 時(shí)間間隔 以秒為單位
@property(nonatomic,assign)NSInteger timeInterval;
@end
#import "UIButton+RespondOnce.h"
#import <objc/runtime.h>
static const void *key = &key;
@implementation UIButton (RespondOnce)
+ (void)load
{
//確保只換一次,因?yàn)橛袝r(shí)候+load可能會(huì)調(diào)用兩次
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Method method1 = class_getInstanceMethod(self, @selector(sendAction:to:forEvent:));
Method method2 = class_getInstanceMethod(self, @selector(ss_sendAction:to:forEvent:));
method_exchangeImplementations(method1, method2);
});
}
/// 關(guān)聯(lián)對(duì)象 - 自定義setter/getter方法
/// @param timeInterval 參數(shù)1 時(shí)間間隔
- (void)setTimeInterval:(NSInteger)timeInterval
{
objc_setAssociatedObject(self, key, @(timeInterval), OBJC_ASSOCIATION_ASSIGN);
}
- (NSInteger)timeInterval
{
return [objc_getAssociatedObject(self, key) longValue];
}
/// exchanged method
/// @param action
/// @param target
/// @param event
- (void)ss_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event
{
//定義static變量俗他,延長(zhǎng)變量生命周期
static BOOL first = YES;
static NSInteger start = 0;
//獲取當(dāng)前時(shí)間戳浑彰,以秒為單位
NSInteger now = [[NSString stringWithFormat:@"%f",[[NSDate date] timeIntervalSince1970]] integerValue];
//判斷是否在時(shí)間間隔內(nèi)
if (now >= start + self.timeInterval) {
first = YES;
}
//如果是時(shí)間間隔周期的首次,記錄start時(shí)間戳拯辙,交換回原點(diǎn)擊方法調(diào)用郭变,first置為NO
if (first) {
start = now;
[self ss_sendAction:action to:target forEvent:event];
first = NO;
}
}
@end
VC中的實(shí)現(xiàn)
- (void)viewDidLoad {
[super viewDidLoad];
UIButton * btn = [[UIButton alloc] initWithFrame:CGRectMake(50, 100, 100, 100)];
btn.timeInterval = 5; //設(shè)置時(shí)間間隔
[btn setBackgroundColor:[UIColor redColor]];
[btn addTarget:self action:@selector(click:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
}
- (void)click:(UIButton *)btn
{
NSLog(@"%s",__func__);
}
@end
測(cè)試結(jié)果
testResult