美文网首页
防止按钮重复点击 runtime处理

防止按钮重复点击 runtime处理

作者: 每天刷两次牙 | 来源:发表于2017-06-16 11:57 被阅读36次

    //  Created by ming on 2017/4/10.//  Copyright © 2017年 wode. All rights reserved.//#import#import#define defaultInter 2//默认时间间隔

    @interface UIButton (UIControl_button)

    @property (nonatomic,assign)NSTimeInterval timerInterVal;// 用这个重复点击加时间隔

    @property (nonatomic,assign)BOOL isSelect; //YES不允许点击 no运行点击

    @end

    //

    //  UIButton+UIControl_button.m

    //

    //  Created by ming on 2017/4/10.

    //  Copyright © 2017年 wode. All rights reserved.

    //

    /*runTime*/

    #import "UIButton+UIControl_button.h"

    @implementation UIButton (UIControl_button)

    -(NSTimeInterval)timerInterVal

    {

    return [objc_getAssociatedObject(self, _cmd)doubleValue];

    }

    -(void)setTimerInterVal:(NSTimeInterval)timerInterVal

    {

    objc_setAssociatedObject(self, @selector(timerInterVal), @(timerInterVal), OBJC_ASSOCIATION_RETAIN_NONATOMIC);

    }

    //runtime 动态绑定 属性

    -(void)setIsSelect:(BOOL)isSelect

    {

    //注意bool类型 需要用OBJC_ASSOCIATION_RETAIN_NONATOMIC 不要用错,否则set方法会赋值出错

    objc_setAssociatedObject(self, @selector(isSelect), @(isSelect), OBJC_ASSOCIATION_RETAIN_NONATOMIC);

    }

    //get方法

    -(BOOL)isSelect

    {

    //_cmd ==@select(isSelect);和set方法一致

    return [objc_getAssociatedObject(self, _cmd)boolValue];

    }

    - (void)resetState{

    [self setIsSelect:NO];

    }

    +(void)load

    {

    //单利

    static dispatch_once_t onceToken;

    _dispatch_once(&onceToken, ^{

    SEL selA = @selector(sendAction:to:forEvent:);

    SEL selB = @selector(mySendAction:to:forEvent:);

    /*

    class_getMethodImplementation(<#__unsafe_unretained Class cls#>, <#SEL name#>) 获取实现方法(IMP实现方法)

    class_getClassMethod  :获取类方法

    class_getInstanceMethod: 获取对象方法

    */

    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 和methodBDE IMP互换一下即可.

    method_exchangeImplementations(methodA, methodB);

    }

    });

    NSLog(@"+load方法");

    }

    //当我们按钮点击执行时间 sendAction 时,将会执行mySendAction

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

    {

    if ([NSStringFromClass(self.class)isEqualToString:@"UIButton"]) {

    self.timerInterVal = self.timerInterVal==0?defaultInter:self.timerInterVal;

    if (self.isSelect) {

    return;

    }else if (self.timerInterVal>0){

    [self performSelector:@selector(resetState) withObject:nil afterDelay:self.timerInterVal];

    }

    }

    //此处 methodA和 methodB方法IMP互换了,实际上执行sendAciont:所以不会死循环.

    self.isSelect = YES;

    [self mySendAction:action to:target forEvent:event];

    }

    相关文章

      网友评论

          本文标题:防止按钮重复点击 runtime处理

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