解決辦法
1.在每次點擊時先取消之前的操作
- (void)cancelBtnAction:(UIButton *)btn {
[[self class] cancelPreviousPerformRequestsWithTarget:self selector:@selector(toDoSomething:) object: btn];
[self performSelector:@selector(toDoSomething:)withObject:btn afterDelay: 0.2f];
}
- (void)toDoSomething:(UIButton *)btn {
NSLog(@"在每次點擊時先取消之前的操作");
}
2.點擊一次后將button的enabled變為NO。在適當的地方把enabled變為YES
3.用Runtime監聽點擊事件,忽略重復點擊,使其規定時間內只響應一次點擊事件
- 為按鈕添加多個target方法
//測試本方法之前記得把runtime注釋打開
[testBtn setTitle:@"Runtime防止重復響應事件" forState:UIControlStateNormal];
[testBtn addTarget:self action:@selector(testBtn:) forControlEvents:UIControlEventTouchUpInside];
[testBtn addTarget:self action:@selector(testBtnTouchDown:) forControlEvents:UIControlEventTouchDown];
[testBtn addTarget:self action:@selector(testBtnTouchUpOutside:) forControlEvents:UIControlEventTouchUpOutside];
testBtn.eventTimeInterval = 2;
解釋一下為什么要添加多個target:如果我們不區分target觸發的方法,那么一個按鈕同時設置多個target,就會出現_wxd_sendAction:to:forEvent:event執行多次,只而觸發了一個target,具體觸發的是哪個自己試驗
- 在UIButton類目中加入屬性
@interface UIButton (Leon)
// 為按鈕添加點擊間隔 eventTimeInterval秒
@property (nonatomic, assign) NSTimeInterval eventTimeInterval;
@end
@interface UIButton ()
/*
***key:方法的名字
***value:是否在eventTimeInterval秒內重復點擊
***問題描述:如果按鈕只增加了一個addTarget:action:forControlEvents:網絡上的實現方案是沒有問題的,如果一個按鈕btn增加多個addTarget:action:forControlEvents:方法,則網絡上那個就不能實現,這個我做了改版
***適用于:同一個按鈕,增加了多個addTarget:action:forControlEvents:方法,方法名字必須不同(不然會出現bug)
***不完善處:如果能獲得是哪種UIControlEvents點擊事件,根據那個點擊事件來作為ignoreEventDic字典的key才能準確防止同一個按鈕,不同的點擊事件,來達成防止重復點擊的效果
*/
@property (nonatomic, strong) NSMutableDictionary *ignoreEventDic;
@end
- 然后進行方法的交換
+ (void)load {
// Method Swizzling
[self swizzleMethod:@selector(sendAction:to:forEvent:) withMethod:@selector(_wxd_sendAction:to:forEvent:) error:nil];
}
- (void)_wxd_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event {
if (!self.ignoreEventDic) {
self.ignoreEventDic = [NSMutableDictionary dictionaryWithCapacity:1];
}
self.eventTimeInterval = self.eventTimeInterval == 0 ? defaultInterval : self.eventTimeInterval;
if ([[self.ignoreEventDic objectForKey:NSStringFromSelector(action)] isEqualToString:@"1"]){
return;
} else if (self.eventTimeInterval > 0){
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(self.eventTimeInterval * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self.ignoreEventDic setObject:@"0" forKey:NSStringFromSelector(action)];
});
}
[self.ignoreEventDic setObject:@"1" forKey:NSStringFromSelector(action)];
// 這里看上去會陷入遞歸調用死循環,但在運行期此方法是和sendAction:to:forEvent:互換的,相當于執行sendAction:to:forEvent:方法,所以并不會陷入死循環。
[self _wxd_sendAction:action to:target forEvent:event];
}
文章是根據前人肩膀上完成,類似的文章很多,自己的總是顯得更加完善
有什么不足之處麻煩留言,必改.