IOS应用防止按钮连续点击

在软件开发项目中,我们经常会碰到点击按钮发送网络请求,或者点击按钮进行页面之间的逻辑跳转。但是有时候遇到一些卡顿的话,用户可能会失去耐心,然后疯狂的点击,这时候就会多次调用按钮触发的方法。在某些特定的情景下会导致页面重复push或者重复发送网络请求。这样的问题既对用户体验有影响,而且还会一定程度上增加服务器的压力。

下面详细讲解几种解决思路,有不完善的地方 希望大家能够纠正。

1.在按钮的触发方法内部做处理

首先创建一个按钮button

@interface ViewController ()
@property(nonatomic,strong)UIButton *button;
@end
- (void)viewDidLoad {
    [super viewDidLoad];

    self.button = [[UIButton alloc] initWithFrame:CGRectMake(200, 200, 100, 100)];
    self.button.backgroundColor = [UIColor redColor];    
    [self.button addTarget:self action:@selector(btnClickedOperations:) forControlEvents:UIControlEventTouchUpInside];

    [self.view addSubview:self.button];
}
- (void)btnClickedOperations:(id)sender{
            static NSTimeInterval time = 0.0;
            NSTimeInterval currentTime = [NSDate date].timeIntervalSince1970;
            //限制用户点击按钮的时间间隔大于1秒钟
              
                if (currentTime - time > 1) {
                //处理逻辑
                    NSLog(@"这是一个测试");
                }
            time = currentTime;
}

最终只有用户的点击时间间隔超过一秒钟 才会再次调用你要处理的逻辑代码。这样就实现了避免用户连续点击按钮带来的影响。

2.同样在方法内部做操作

在按钮方法内部对按钮的状态进行控制 在执行完指定的操作后  用户才可以继续点击按钮  同样可以避免连续点击带来的问题   这种方法适合用在处理逻辑时间比较久的情况 ,如果处理逻辑时间很短暂 那么就起不到限制用户连续点击的情况
- (void)test:(UIButton *)btn{
    btn.enabled = NO;
    //处理逻辑
    btn.enabled = YES;
}

如果想控制按钮的时间间隔同样可以加一个延迟的方法

- (void)test:(UIButton *)btn{
    btn.enabled = NO;
    //处理逻辑
     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"btnClickedOperations");
        btn.enabled = YES;
    });
}

实现效果

第三种:使用runtime,一劳永逸我这设的是0.5秒内不会被重复点击

#import <UIKit/UIKit.h>

@interface UIControl (repeatedClick)
/**
 可以重复点击的时间间隔
 默认为0 不对按钮重复点击处理
 */
@property (nonatomic,assign) NSTimeInterval timeInterval;//用这个给重复点击加间隔
/**
 内部属性用于判断是否忽略替换的点击事件
 */
@property (nonatomic,assign) BOOL isIgnoreEvent;
@end
#import "UIControl+repeatedClick.h"
#import <objc/runtime.h>
#define defaultInterval 0//默认时间间隔  0.25
@implementation UIControl (repeatedClick)
- (NSTimeInterval)timeInterval{
    return [objc_getAssociatedObject(self,_cmd)doubleValue];
}

- (void)setTimeInterval:(NSTimeInterval)timeInterval{
    objc_setAssociatedObject(self,@selector(timeInterval),@(timeInterval),OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (void)setIsIgnoreEvent:(BOOL)isIgnoreEvent{
    objc_setAssociatedObject(self,@selector(isIgnoreEvent),@(isIgnoreEvent),OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (BOOL)isIgnoreEvent{
    return [objc_getAssociatedObject(self,_cmd)boolValue];
}

- (void)resetState{
    [self setIsIgnoreEvent:NO];
}

+ (void)load{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        SEL selA = @selector(sendAction:to:forEvent:);
        SEL selB = @selector(mySendAction:to:forEvent:);
        Method methodA = class_getInstanceMethod(self, selA);
        Method methodB = class_getInstanceMethod(self, selB);
        //将methodB的实现添加到系统方法中也就是说将methodA方法指针添加成方法methodB的返回值表示是否添加成功
        BOOL isAdd = class_addMethod(self, selA,method_getImplementation(methodB),method_getTypeEncoding(methodB));
        //添加成功了说明本类中不存在methodB所以此时必须将方法b的实现指针换成方法A的,否则b方法将没有实现。
        if(isAdd) {
            class_replaceMethod(self, selB,method_getImplementation(methodA),method_getTypeEncoding(methodA));
        }else{
            //添加失败了说明本类中有methodB的实现,此时只需要将methodA和methodB的IMP互换一下即可。
            method_exchangeImplementations(methodA, methodB);
        }
    });
}

- (void)mySendAction:(SEL)action to:(id)target forEvent:(UIEvent*)event{
    if([NSStringFromClass(self.class) isEqualToString:@"UIButton"]) {
        self.timeInterval = self.timeInterval == 0 ? defaultInterval:self.timeInterval;
        if(self.isIgnoreEvent){
            return;
        }else if(self.timeInterval > 0){
            [self performSelector:@selector(resetState)withObject:nil afterDelay:self.timeInterval];
        }
    }
    //此处methodA和methodB方法IMP互换了,实际上执行sendAction;所以不会死循环
    self.isIgnoreEvent = YES;
    [self mySendAction:action to:target forEvent:event];
}
@end

 

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值