天天看點

iOS小技巧--用runtime 解決UIButton 重複點選問題iOS小技巧–用runtime 解決UIButton 重複點選問題

iOS小技巧–用runtime 解決UIButton 重複點選問題

什麼是這個問題

我們的按鈕是點選一次響應一次, 即使頻繁的點選也不會出問題, 可是某些場景下還偏偏就是會出問題.

通常是如何解決

我們通常會在按鈕點選的時候設定這個按鈕不可點選. 等待0.xS的延時後,在設定回來; 或者在操作結束的時候設定可以點選.

- (IBAction)clickBtn1:(UIbutton *)sender
{
    sender.enabled = NO;
    doSomething
    sender.enabled = YES;
}
           

如果涉及到按鈕不同狀态不同樣式的時候, 用enabled不見得夠用.還得額外加個變量來記錄狀态.

- (IBAction)clickBtn1:(UIbutton *)sender
{
    if (doingSomeThing) return;

    doingSomeThing = YES;
    doSomething
    doingSomeThing = NO;
}
           

筆者舉的例子是直接在響應事件的周期内直接禁止點選的. 如果想做1秒内禁止重複點選的話,則得用

performSelector:withObject:afterDelay:

漂亮的解決是怎樣的

有了重複的代碼段就是有了一個共性, 就可以抽象出來.

我們可以給按鈕添加一個屬性

重複點選間隔

, 通過設定這個屬性來控制再次接受點選事件的時間間隔.

@interface UIControl (XY)
@property (nonatomic, assign) NSTimeInterval uxy_acceptEventInterval;   // 可以用這個給重複點選加間隔
@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
           

在我們的點選事件裡呢,對點選事件做下過濾

- (void)__uxy_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event
{
    if (NSDate.date.timeIntervalSince1970 - self.uxy_acceptedEventTime < self.uxy_acceptEventInterval) return;

    if (self.uxy_acceptEventInterval > )
    {
        self.uxy_acceptedEventTime = NSDate.date.timeIntervalSince1970;
    }

    [self __uxy_sendAction:action to:target forEvent:event];
}
           

實際使用起來就是這個樣子

UIButton *tempBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    [tempBtn addTarget:self action:@selector(clickWithInterval:) forControlEvents:UIControlEventTouchUpInside];
    tempBtn.uxy_acceptEventInterval = ;
           

文章至此就結束了.雖然不推薦大範圍用runtime, 但是小範圍内使用還是可以解決不少小問題的.