參考鏈接:
http://www.cocoachina.com/ios/20150911/13260.html
問題描述:
? ? ? 我們的按鈕是點(diǎn)擊一次響應(yīng)一次, 即使頻繁的點(diǎn)擊也不會出問題, 可是某些場景下還偏偏就是會出問題.
通常是如何解決
我們通常會在按鈕點(diǎn)擊的時候設(shè)置這個按鈕不可點(diǎn)擊. 等待0.xS的延時后,在設(shè)置回來; 或者在操作結(jié)束的時候設(shè)置可以點(diǎn)擊.
- (IBAction)clickBtn1:(UIbutton *)sender
{
sender.enabled = NO;
doSomething
sender.enabled = YES;
}
如果涉及到按鈕不同狀態(tài)不同樣式的時候, 用enabled不見得夠用.還得額外加個變量來記錄狀態(tài).
- (IBAction)clickBtn1:(UIbutton *)sender
{
if (doingSomeThing) return;
doingSomeThing = YES;
doSomething
doingSomeThing = NO;
}
上面的例子是直接在響應(yīng)事件的周期內(nèi)直接禁止點(diǎn)擊的. 如果想做1秒內(nèi)禁止重復(fù)點(diǎn)擊的話,則得用performSelector:withObject:afterDelay:
漂亮的解決是怎樣的
有了重復(fù)的代碼段就是有了一個共性, 就可以抽象出來.
我們可以給按鈕添加一個屬性重復(fù)點(diǎn)擊間隔, 通過設(shè)置這個屬性來控制再次接受點(diǎn)擊事件的時間間隔.
@interface UIControl (XY)
@property (nonatomic, assign) NSTimeInterval uxy_acceptEventInterval;? // 可以用這個給重復(fù)點(diǎn)擊加間隔
@end
static const char *UIControl_acceptEventInterval = "UIControl_acceptEventInterval";
- (NSTimeInterval)uxy_acceptEventInterval
{
return [objc_getAssociatedObject(self, UIControl_acceptEventInterval) doubleValue];
}
- (void)setUxy_acceptEventInterval:(NSTimeInterval)uxy_acceptEventInterval
{
objc_setAssociatedObject(self, UIControl_acceptEventInterval, @(uxy_acceptEventInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
在app啟動的時候,我們hook 所有的按鈕的 event
@implementation UIControl (XY)
+ (void)load
{
Method a = class_getInstanceMethod(self, @selector(sendAction:to:forEvent:));
Method b = class_getInstanceMethod(self, @selector(__uxy_sendAction:to:forEvent:));
method_exchangeImplementations(a, b);
}
@end
在我們的點(diǎn)擊事件里呢,對點(diǎn)擊事件做下過濾
- (void)__uxy_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event
{
if (self.uxy_ignoreEvent) return;
if (self.uxy_acceptEventInterval > 0)
{
self.uxy_ignoreEvent = YES;
[self performSelector:@selector(setUxy_ignoreEvent:) withObject:@(NO) afterDelay:self.uxy_acceptEventInterval];
}
實(shí)際使用起來就是這個樣子
UIButton *tempBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[tempBtn addTarget:self action:@selector(clickWithInterval:) forControlEvents:UIControlEventTouchUpInside];
tempBtn.uxy_acceptEventInterval = 0.5;
雖然不推薦大范圍用runtime, 但是小范圍內(nèi)使用還是可以解決不少小問題的.