iOS_设置 UIButton 点击时间间隔,防止连续重复点击

  • 使用场景
    在实际应用场景中,有几个业务场景需要控制UIButton响应事件的时间间隔。
  1. 当点击按钮来执行网络请求时,若请求耗时稍长,用户往往会多次点击。这样,就执行了多次请求,造成资源浪费。
  2. 在移动终端设备性能较差时,连续点击按钮会执行多次事件(比如push出来多个viewController)。
  3. 防止暴力点击。
  • 解决3种方案:

1. 设置enabled或userInteractionEnabled属性(利用dispach_after方法)

//按钮第二次点击事件触发的等待时间
#define Button_Seconds_Time(_seconds_) \
static BOOL shouldPrevent; \
if (shouldPrevent) return; \
shouldPrevent = YES; \
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)((_seconds_) * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ \
shouldPrevent = NO; \
});
(void)tapBtn:(UIButton *)btn {
    NSLog(@"按钮点击...");
    btn.enabled = NO;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        btn.enabled = YES;
    });
}

2. 借助cancelPreviousPerformRequestsWithTarget:selector:object实现


- (void)tapBtn:(UIButton *)btn {
    NSLog(@"按钮点击了...");
    // 此方法会在连续点击按钮时取消之前的点击事件,从而只执行最后一次点击事件}
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(buttonClickedAction:) object:btn];
    // 多长时间后做某件事情
    [self performSelector:@selector(buttonClickedAction:) withObject:btn afterDelay:2.0];
}
 
- (void)buttonClickedAction:(UIButton *)btn {
    NSLog(@"真正开始执行业务 - 比如网络请求...");
}
  • 问题:会出现延时现象,并且需要对大量的UIButton做处理,工作量大,不方便。

3. 通过runtime交换方法实现

  • 通过Runtime交换UIControl的响应事件方法,从而控制响应事件的时间间隔。

  • 实现步骤如下:

  1. 创建一个UIControl的分类,使用runtime增加public属性sz_eventInterval和private属性sz_eventInvalid。
  2. 在+load方法中使用runtime将UIButton的-sendAction:to:forEvent:方法与自定义的sz_sendAction:to:forEvent:方法进行交换
  3. 使用sz_eventInterval作为控制sz_eventInvalid的计时因子,用sz_eventInvalid控制UIButton的event事件是否有效。

#import "UIControl+Extension.h"
#import <objc/runtime.h>

 
@interface UIControl()
 
/** 是否失效 - 即不可以点击 */
@property (nonatomic, assign) BOOL sz_eventInvalid;
 
@end
 
@implementation UIButton (Extension)
 
+ (void)load {
    // 交换方法
    Method clickMethod = class_getInstanceMethod(self, @selector(sendAction:to:forEvent:));
    Method sz_clickMethod = class_getInstanceMethod(self, @selector(sz_sendAction:to:forEvent:));
    method_exchangeImplementations(clickMethod, sz_clickMethod);
}
 
#pragma mark - click
 
- (void)sz_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event {
    if (!self.sz_eventInvalid) {
        self.sz_eventInvalid = YES;
        [self sz_sendAction:action to:target forEvent:event];
        [self performSelector:@selector(setSz_eventInvalid:) withObject:@(NO) afterDelay:self.sz_eventInterval];
    }
}
 
#pragma mark - set | get
- (NSTimeInterval)sz_eventInterval {
    return [objc_getAssociatedObject(self, _cmd) doubleValue];
}
 
- (void)setSz_eventInterval:(NSTimeInterval)sz_eventInterval {
    objc_setAssociatedObject(self, @selector(sz_eventInterval), @(sz_eventInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
 
- (BOOL)sz_eventInvalid {
    return [objc_getAssociatedObject(self, _cmd) boolValue];
}
 
- (void)setSz_eventInvalid:(BOOL)sz_eventInvalid {
    objc_setAssociatedObject(self, @selector(sz_eventInvalid), @(sz_eventInvalid), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值