UIButton是我們iOS開發中常用的控件,連續/抖動點擊也是用戶使用中常發生的 !項目之后發現網上解決這一體驗問題的資料還是蠻多的,但還是要自己做份筆記,方便下次查閱!
方案一:
- (void)viewDidLoad{ [super viewDidLoad]; // 1. 創建 btn 並添加點擊事件 UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom]; [btn setFrame:CGRectMake(100, 100, 100, 60)]; btn.backgroundColor = [UIColor greenColor]; [btn addTarget:self action:@selector(clickbtn:) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:btn]; }
// 2. 延時時間設置為 t (此處設置為1.0s) ,所以凡是前后兩次點擊時間間隔不超過1.0s都會被取消 - (void)clickbtn:(UIButton *)btn{ NSLog(@" %s ",__FUNCTION__); [[self class] cancelPreviousPerformRequestsWithTarget:self selector:@selector(handleEvent:) object:btn]; [self performSelector:@selector(handleEvent:) withObject:btn afterDelay:1.0]; } // 3. 點擊事件的處理方法 - (void)handleEvent:(UIButton *)btn{ NSLog(@" %s ",__FUNCTION__); }
方案二:給 UIButton 添加分類 ,方便項目中所有的 UIButton 實例都可以方便使用!
主要代碼:
// .h 文件 #import <UIKit/UIKit.h> @interface UIButton (ClickEventTime) @property (nonatomic,assign) NSTimeInterval custom_acceptEventInterval; @end
// .m 文件 #import "UIButton+ClickEventTime.h" #import <objc/runtime.h> @implementation UIButton (ClickEventTime) /** 1. 攔截系統方法 2. 用自定義的方法替換第一步攔截的系統方法 3. 在自定義方法里嘗試終止對連續點擊的前面幾次的響應 */ #pragma mark ----- 攔截系統方法 +(void)load{ SEL sysSEL = @selector(sendAction:to:forEvent:); Method systemMethod = class_getInstanceMethod(self, sysSEL); SEL customSEL = @selector(custom_sendAction:to:forEvent:); Method customMethod = class_getInstanceMethod(self, customSEL); method_exchangeImplementations(systemMethod, customMethod); } #pragma mark ----- 用於替換系統方法的自定義方法 - (void)custom_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event{ // 是否小於設定的時間間隔 BOOL needSendAction = (NSDate.date.timeIntervalSince1970 - self.custom_acceptEventTime >= self.custom_acceptEventInterval); // 更新上一次點擊時間戳 if (self.custom_acceptEventInterval > 0) { self.custom_acceptEventTime = NSDate.date.timeIntervalSince1970; } if (needSendAction) { // 兩次點擊的時間間隔小於設定的時間間隔時,才執行響應事件 [self custom_sendAction:action to:target forEvent:event]; }else{ return; } } - (NSTimeInterval )custom_acceptEventTime{ return [objc_getAssociatedObject(self, "UIControl_acceptEventTime") doubleValue]; } - (void)setCustom_acceptEventTime:(NSTimeInterval)custom_acceptEventTime{ objc_setAssociatedObject(self, "UIControl_acceptEventTime", @(custom_acceptEventTime), OBJC_ASSOCIATION_RETAIN_NONATOMIC); } #pragma mark ------ 關聯 - (NSTimeInterval )custom_acceptEventInterval{ return [objc_getAssociatedObject(self, "UIControl_acceptEventInterval") doubleValue]; } - (void)setCustom_acceptEventInterval:(NSTimeInterval)custom_acceptEventInterval{ objc_setAssociatedObject(self, "UIControl_acceptEventInterval", @(custom_acceptEventInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC); } @end