有幾個實際業務場景需要控制?UIButton?響應事件的時間間隔。比如:
1、當通過點擊按鈕來執行網絡請求時,若請求耗時稍長,用戶往往會再點一次。這樣,就執行了兩次請求,造成了資源浪費。
2、在移動終端性能較差時(比如?iPhone 6?升級到?iOS 11?:sweat_smile:),連續點擊按鈕會執行多次事件(比如push出來多個?viewController?)。
3、防止暴力點擊。
控制按鈕響應事件時間間隔的方案不止一種。比如:
方案 1:通過?UIButton?的?enabled?屬性和?userInteractionEnabled?屬性控制按鈕是否可點擊。此方案在邏輯上比較清晰、易懂,但具體代碼書寫分散,常常涉及多個方法。
- (void)buttonClicked:(UIButton *)sender {? ?
? ? sender.enabled = NO;? ?
? ? dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{? ? ? ? sender.enabled = YES;? ? });}
方案2:通過NSObject的?+cancelPreviousPerformRequestsWithTarget:selector:object:?方法和?-performSelector:withObject:afterDelay:?方法控制按鈕的響應事件的執行時間間隔。此方案會在連續點擊按鈕時取消之前的點擊事件,從而只執行最后一次點擊事件,會出現延遲現象。
- (void)buttonClicked:(UIButton *)sender {? ?
? ? [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(buttonClickedAction:) object:sender];? ? [self performSelector:@selector(buttonClickedAction:) withObject:sender afterDelay:2.0];}
在需要對大量?UIButton?做控制的場景中,方案1和方案2會比較不方便。針對此場景,著重說一下方案3。
方案3:通過Runtime控制UIButton響應事件的時間間隔。思路如下:
1、創建一個?UIButton?的類別,使用?runtime?為?UIButton?增加?public?屬性?qi_eventInterval?和?private?屬性?eventUnavailable?。
2、在+load方法中使用?runtime?將?UIButton?的?-sendAction:to:forEvent:?方法與自定義的?-qi_sendAction:to:forEvent:?方法交換?Implementation?。
3、使用?qi_eventInterval?作為控制?eventUnavailable?的計時因子,用?eventUnavailable?開控制?UIButton?的?event?事件是否有效。
方案3可以對所有UIButton生效,具體實現代碼如下:
@interface UIButton (QiEventInterval)@property (nonatomic, assign) NSTimeInterval qi_eventInterval;@end
#import "UIButton+QiEventInterval.h"#import <objc/runtime.h>static char * const qi_eventIntervalKey = "qi_eventIntervalKey";static char * const eventUnavailableKey = "eventUnavailableKey";@interface UIButton ()@property (nonatomic, assign) BOOL eventUnavailable;@end@implementation UIButton (QiEventInterval)+ (void)load {? ?
? ? Method method = class_getInstanceMethod(self, @selector(sendAction:to:forEvent:));? ? Method qi_method = class_getInstanceMethod(self, @selector(qi_sendAction:to:forEvent:));? ? method_exchangeImplementations(method, qi_method);}#pragma mark - Action functions- (void)qi_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event {? ?
? ? if (self.eventUnavailable == NO) {? ? ? ? self.eventUnavailable = YES;? ? ? ? [self qi_sendAction:action to:target forEvent:event];? ? ? ? [self performSelector:@selector(setEventUnavailable:) withObject:@(NO) afterDelay:self.qi_eventInterval];? ? }}#pragma mark - Setter & Getter functions- (NSTimeInterval)qi_eventInterval {? ?
? ? return [objc_getAssociatedObject(self, qi_eventIntervalKey) doubleValue];}- (void)setQi_eventInterval:(NSTimeInterval)qi_eventInterval {? ?
? ? objc_setAssociatedObject(self, qi_eventIntervalKey, @(qi_eventInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);}- (BOOL)eventUnavailable {? ?
? ? return [objc_getAssociatedObject(self, eventUnavailableKey) boolValue];}- (void)setEventUnavailable:(BOOL)eventUnavailable {? ?
? ? objc_setAssociatedObject(self, eventUnavailableKey, @(eventUnavailable), OBJC_ASSOCIATION_RETAIN_NONATOMIC);}@end
使用方法:
UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];/* here is some button's configuration codes */[self.view addSubview:button];? ? //! 設置按鈕的點擊響應間隔時間button.qi_eventInterval = 2.0;
效果展示:
默認Button點擊效果:
不設置qi_eventInterval (默認為0)
設置qi_eventInterval為2秒:
設置qi_eventInterval為2秒
可從Github獲取?工程源碼
來自http://www.qingpingshan.com/rjbc/ios/393222.html