iOS 使用runtime 防止按钮快速点击

在我们平常的开发当中经常会碰到测试会去快速点击按钮。如果按钮没有做时间拦截处理,那么就会出现按钮的方法会执行多次,这样是不行的,我在这里也是参照网上的有一些资料,写了个demo,有需要的朋友可以直接拿走。分类都知道是不能直接添加属性的,因为添加属性他不会自动生成get和set放法,运行就会崩溃,这就需要我们用runtime来做点事情了。

runtime的作用什么,在开发中能帮助我们做些什么事情?

  • 1.最常见的就是字典转模型:MJExtention, YYModel等底层均使用runtime操作,使用class_getProperty来获取模型当中的所有属性,最后与返回的数据进行比对,有相同的key就使用KVC进行赋值操作,也可访问私有属性进行取值和赋值操作
  • 2.可以在运行的时候交换系统的方法,让他执行我们自己的方法方便进行扩展操作
  • 3.为分类添加属性并关联对象

这里我就使用runtime动态的为分类添加属性以便进行扩展操作

  • 由于按钮是继承UIControl的,我这里就直接为UIControl添加分类即可
#import <UIKit/UIKit.h>
@interface UIControl (BtnQuickLimit)
//添加两个属性

// 间隔多少秒才能响应事件
@property(nonatomic, assign) NSTimeInterval  acceptEventInterval;
//是否能执行方法
@property(nonatomic, assign) BOOL ignoreEvent;

@end
#import "UIControl+BtnQuickLimit.h"
#import <objc/runtime.h>

static const char * UIControl_acceptEventInterval = "UIControl_acceptEventInterval";
static const char * UIControl_ignoreEvent = "UIControl_ignoreEvent";

@implementation UIControl (BtnQuickLimit)

-(void)setAcceptEventInterval:(double)acceptEventInterval {
    //关联属性对象
    objc_setAssociatedObject(self, UIControl_acceptEventInterval,@(acceptEventInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

-(NSTimeInterval)acceptEventInterval{
    return [objc_getAssociatedObject(self, UIControl_acceptEventInterval) doubleValue];
}

-(void)setIgnoreEvent:(BOOL)ignoreEvent {
   //关联属性对象
    objc_setAssociatedObject(self, UIControl_ignoreEvent, @(ignoreEvent), OBJC_ASSOCIATION_ASSIGN);
}

-(BOOL)ignoreEvent{
    return [objc_getAssociatedObject(self, UIControl_ignoreEvent) boolValue];
}

//所有类即将加入内存的时候都会走load方法,所以我们在这个里面交换方法
+(void)load{
    Method a = class_getInstanceMethod(self, @selector(sendAction:to:forEvent:));
    Method b = class_getInstanceMethod(self, @selector(swizzing_sendAction:to:forEvent:));
    method_exchangeImplementations(a, b);
}

-(void)swizzing_sendAction:(SEL)action to:(id)tagert forEvent:(UIEvent*)event{
    if (self.ignoreEvent) {
        NSLog(@"你点击的太快了");
        return;
    }
    if (self.acceptEventInterval>0) {
        self.ignoreEvent = YES;
//之前是写的有点问题,现在改了一下,把下面这段话给注释掉,就会只响应一次点击,前提是:acceptEventInterval 的数据必须大于0,否则会一直走调用的方法
      // [self performSelector:@selector(setIgnoreWithNo) withObject:nil afterDelay:self.acceptEventInterval];
//如果想要按钮延迟一定的时间去响应事件,就可以打开上面的方法即可
[self performSelector:@selector(setIgnoreWithNo) withObject:nil afterDelay:self.acceptEventInterval];
    }
//当前按钮调用该方法
    [self swizzing_sendAction:action to:tagert forEvent:event];
}
-(void)setIgnoreWithNo{
    self.ignoreEvent = NO;
}
@end

最后在UIViewController中创建按钮的时候直接使用

-(void)creatSubView {
    self.view.backgroundColor = [UIColor whiteColor];
    UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
    btn.frame = CGRectMake(200, 200, 100, 50);
    btn.backgroundColor = [UIColor redColor];
    btn.acceptEventInterval = 1.0;
    [btn setTitle:@"快速点击" forState:UIControlStateNormal];
    [self.view addSubview:btn];
    [btn addTarget:self action:@selector(quiklyClick) forControlEvents:UIControlEventTouchUpInside];
}

-(void)quiklyClick{
    NSLog(@"快速点击。。。。。。。。");
}

文章会持续更新,有什么不好的地方还请路过的大神多多指正。相互学习

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容