美文网首页
按钮点击单位时间内不论调用多少次,只执行一次

按钮点击单位时间内不论调用多少次,只执行一次

作者: GemShi | 来源:发表于2020-03-14 12:38 被阅读0次
思考

怎么通过留给外部一个简单的API去实现一个按钮在一定时间间隔内不论点击多少次,只执行一次?
例如,实际开发中,当点击按钮进行网络请求的时候,在接收到响应之前,user可能会暴力点击,如果单位时间内不停的发送网络请求,不仅耗性能,单位时间过后连续的响应也会造成不良的用户体验。

大致步骤

1.首先给按钮一个属性,记录目标时间间隔(创建UIControl分类,通过添加关联对象实现)
2.使用runtime方法交换,捕获系统方法并交换(sendAction:To:ForEvent:)
3.自定义点击事件(添加需要判断时间间隔的逻辑)

具体实现

给UIButton添加RespondOnce分类

@interface UIButton (RespondOnce)

/// 时间间隔 以秒为单位
@property(nonatomic,assign)NSInteger timeInterval;

@end
#import "UIButton+RespondOnce.h"
#import <objc/runtime.h>

static const void *key = &key;

@implementation UIButton (RespondOnce)

+ (void)load
{
    //确保只换一次,因为有时候+load可能会调用两次
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Method method1 = class_getInstanceMethod(self, @selector(sendAction:to:forEvent:));
        Method method2 = class_getInstanceMethod(self, @selector(ss_sendAction:to:forEvent:));
        method_exchangeImplementations(method1, method2);
    });
}

/// 关联对象 - 自定义setter/getter方法
/// @param timeInterval 参数1 时间间隔
- (void)setTimeInterval:(NSInteger)timeInterval
{
    objc_setAssociatedObject(self, key, @(timeInterval), OBJC_ASSOCIATION_ASSIGN);
}

- (NSInteger)timeInterval
{
    return [objc_getAssociatedObject(self, key) longValue];
}

/// exchanged method
/// @param action
/// @param target
/// @param event 
- (void)ss_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event
{
    //定义static变量,延长变量生命周期
    static BOOL first = YES;
    static NSInteger start = 0;
    
    //获取当前时间戳,以秒为单位
    NSInteger now = [[NSString stringWithFormat:@"%f",[[NSDate date] timeIntervalSince1970]] integerValue];
    
    //判断是否在时间间隔内
    if (now >= start + self.timeInterval) {
        first = YES;
    }
    
    //如果是时间间隔周期的首次,记录start时间戳,交换回原点击方法调用,first置为NO
    if (first) {
        start = now;
        [self ss_sendAction:action to:target forEvent:event];
        first = NO;
    }
}

@end

VC中的实现

- (void)viewDidLoad {
    [super viewDidLoad];
    
    UIButton * btn = [[UIButton alloc] initWithFrame:CGRectMake(50, 100, 100, 100)];
    btn.timeInterval = 5;   //设置时间间隔
    [btn setBackgroundColor:[UIColor redColor]];
    [btn addTarget:self action:@selector(click:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:btn];
}

- (void)click:(UIButton *)btn
{
    NSLog(@"%s",__func__);
}

@end
测试结果
testResult

相关文章

  • 按钮点击单位时间内不论调用多少次,只执行一次

    思考 怎么通过留给外部一个简单的API去实现一个按钮在一定时间间隔内不论点击多少次,只执行一次?例如,实际开发中,...

  • Android 防误触

    防止按钮短时间内多次点击。使用kotlin扩展方法,限制500毫秒内点击一次。 调用处

  • 防抖、节流(亲测有效)

    防抖(一段时间内,只执行最后一次。通俗点,不管你点多少次,执行最后一次) 节流(每段时间内,只执行一次。通俗点,你...

  • 函数节流

    函数节流的定义: 规定的单位时间内只执行一次,如果在单位时间内执行了多次,那么最后也只会执行一次。

  • 节流函数及其应用

    定义:在一个单位时间内只触发一次,如果在这个单位时间内多次触发,只执行一次 定义节流函数 onload函数取出节流...

  • Rails开发后台调用API功能-faraday+sidekiq

    流程设计 前端点击按钮‘开始同步’ 异步执行,remote: true controller运行rsync,调用后...

  • 节流与防抖

    节流-throttle 节流的意思是,规定时间内,只触发一次。比如我们设定500ms,在这个时间内,无论点击按钮多...

  • 节流防抖

    何谓节流和防抖? 节流节流的意思是,规定时间内,只触发一次。比如我们设定500ms,在这个时间内,无论点击按钮多少...

  • 属性动画只能运行一次吗,非也

    写了个属性动画 发现这个按钮无论点多少次都是只执行了第一次,why? 加log 打印如下 说明属性动画执行的时候是...

  • 防抖、节流

    防抖 一定时间内多次触发事件只执行最后一次 节流 规定时间内只执行一次

网友评论

      本文标题:按钮点击单位时间内不论调用多少次,只执行一次

      本文链接:https://www.haomeiwen.com/subject/qbnmshtx.html