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

作者: 龙龙_龙 | 来源:发表于2018-05-07 16:11 被阅读181次
    在我们平常的开发当中经常会碰到测试会去快速点击按钮。如果按钮没有做时间拦截处理,那么就会出现按钮的方法会执行多次,这样是不行的,我在这里也是参照网上的有一些资料,写了个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;
            [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 = 5.0;
        [btn setTitle:@"快速点击" forState:UIControlStateNormal];
        [self.view addSubview:btn];
        [btn addTarget:self action:@selector(quiklyClick) forControlEvents:UIControlEventTouchUpInside];
    }
    
    -(void)quiklyClick{
        NSLog(@"快速点击。。。。。。。。");
    }
    

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

    相关文章

      网友评论

      • 8dd6d4b40240:-(void)setAcceptEventInterval:(double)acceptEventInterval {
        //关联属性对象
        objc_setAssociatedObject(self, UIControl_acceptEventInterval

        属性的修饰符写错了吧
      • li_礼光:龙大神就是牛逼啊,6666,学习了

      本文标题:iOS 使用runtime 防止按钮快速点击

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