防止按钮快速连续点击造成多次响应的方法

用户快速点击某个按钮,导致页面重复push或者重复发送网络请求。这样的问题既对用户体验有影响,而且还会一定程度上增加服务器的压力。

主要使用以下办法:

1、在每次点击时先取消之前的操作

- (void)buttonClicked:(id)sender
{
   //这里是关键,点击按钮后先取消之前的操作,再进行需要进行的操作
   [[self class] cancelPreviousPerformRequestsWithTarget:self selector:@selector(buttonClicked:) object:sender];
   [self performSelector:@selector(buttonClicked: )withObject:sender afterDelay:0.2f];
}

2、点击后将按钮置为不可点击状态,几秒后恢复

-(void)buttonClicked:(id)sender{
   self.button.enabled = NO;
   [self performSelector:@selector(changeButtonStatus) withObject:nil afterDelay:1.0f];//防止用户重复点击
}

-(void)changeButtonStatus{
    self.button.enabled = YES;
}

3、利用运行时

//  UIControl+Custom.h
//  Created by ocarol on 16/8/16.
//  Copyright © 2016年 ocarol. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface UIControl (Custom)
@property (nonatomic, assign) NSTimeInterval custom_acceptEventInterval;// 可以用这个给重复点击加间隔
@end

在 UIControl+Custom.m 文件中实现方法交换(妥善的做法是:先添加方法,如果方法已经存在,就替换原方法),在 UIControl+Custom.m 文件的代码为:

//  UIControl+Custom.m
//  Created by ocarol on 16/8/16.
//  Copyright © 2016年 ocarol. All rights reserved.
//

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

@interface UIControl()
@property (nonatomic, assign) NSTimeInterval custom_acceptEventTime;
@end


@implementation UIControl (Custom)

+ (void)load{
    Method systemMethod = class_getInstanceMethod(self, @selector(sendAction:to:forEvent:));
    SEL sysSEL = @selector(sendAction:to:forEvent:);

    Method customMethod = class_getInstanceMethod(self, @selector(custom_sendAction:to:forEvent:));
    SEL customSEL = @selector(custom_sendAction:to:forEvent:);

    //添加方法 语法:BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types) 若添加成功则返回No
    // cls:被添加方法的类  name:被添加方法方法名  imp:被添加方法的实现函数  types:被添加方法的实现函数的返回值类型和参数类型的字符串
    BOOL didAddMethod = class_addMethod(self, sysSEL, method_getImplementation(customMethod), method_getTypeEncoding(customMethod));

    //如果系统中该方法已经存在了,则替换系统的方法  语法:IMP class_replaceMethod(Class cls, SEL name, IMP imp,const char *types)
    if (didAddMethod) {
        class_replaceMethod(self, customSEL, method_getImplementation(systemMethod), method_getTypeEncoding(systemMethod));
    }else{
        method_exchangeImplementations(systemMethod, customMethod);

    }
}

- (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);
}

- (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);
}

- (void)custom_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event{

   // 如果想要设置统一的间隔时间,可以在此处加上以下几句
   // 值得提醒一下:如果这里设置了统一的时间间隔,会影响UISwitch,如果想统一设置,又不想影响UISwitch,建议将UIControl分类,改成UIButton分类,实现方法是一样的
   // if (self.custom_acceptEventInterval <= 0) {
   //     // 如果没有自定义时间间隔,则默认为2秒
   //    self.custom_acceptEventInterval = 2;
   // }

    // 是否小于设定的时间间隔
    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];
    }


}
@end

使用举例:

UIButton *tempBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[tempBtn addTarget:self action:@selector(clickWithInterval:) forControlEvents:UIControlEventTouchUpInside];
tempBtn.uxy_acceptEventInterval = 0.5;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值