按钮猛点,多次响应问题

    今天发现项目中一个bug,猛点按钮进入下一控制器时,结果push了两次,然后点击返回,黑屏了,主要原因在于,猛点的时候,处理点击事件时又重新响应了相应事件,也就是说响应方法在猛点下调用了两次。

    解决办法,就是让按钮点击处理事件的一秒内(不一定一秒可以自己测试一下)不能重复响应事件,于是写了个UIButton分类。

    代码如下:

    头文件:

#import

@interface UIButton (Extent)

@property(nonatomic,assign)BOOL isDoing;

@property(nonatomic,copy)NSString *actionSelName;

@property(nonatomic,strong)id target;

@end

   源文件:

static const char  bntExtentIsDoing;

static const char  BtnExtentActionSel;

static const char BtnExtentTarget;

#import "UIButton+Extent.h"

#import

@implementation UIButton(Extent)

-(void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents

{

           NSString *actionSelName = NSStringFromSelector(action);

           [self setActionSelName:actionSelName];

           [self setTarget:target];

            [self setIsDoing:NO];

            //替换按钮点击的响应事件 

            return [super addTarget:self action:@selector(btnExtentClicked:)   forControlEvents:controlEvents];

}

-(void)btnExtentClicked:(UIButton*)btn

{

           BOOL isDoing = [self isDoing];

            [self setIsDoing:YES];

            if (!isDoing) {

                      SEL action = NSSelectorFromString([self actionSelName]);

                      id target = [self target];

                     /*

                     ARC情况下会有警告,因为这种调用,action是通过字符串创建的,运行时才能决定     action对应方法的函数签名,比如有返回值,编译器不知道该如何处理,存在出现内存泄漏情况, 而编译器不知道,故而给出警告。那就直接使用IMP指针避免让人看了烦躁的警告!

                     [target performSelector:action withObject:btn];

                    */

                    IMP imp = [target methodForSelector:action];

                    void (*funaction)(id target,SEL sel,id btn) = (void*)imp;

funaction(target,action,btn);

                     [self performSelector:@selector(resetIsDoing) withObject:nil afterDelay:1];

           }

}

-(void)resetIsDoing

{

           [self setIsDoing:NO];

}

-(id)target

{

            return objc_getAssociatedObject(self, &BtnExtentTarget);

}

-(void)setTarget:(id)target

{

             objc_setAssociatedObject(self, &BtnExtentTarget, target, OBJC_ASSOCIATION_ASSIGN);

}

-(NSString*)actionSelName

{

              return objc_getAssociatedObject(self, &BtnExtentActionSel);

}

-(void)setActionSelName:(NSString *)actionSelName

{

             objc_setAssociatedObject(self, &BtnExtentActionSel, actionSelName, OBJC_ASSOCIATION_COPY);

}

-(void)dealloc

{

           objc_removeAssociatedObjects(self);

}

-(BOOL)isDoing

{

          id  result = objc_getAssociatedObject(self, &bntExtentIsDoing);

          return [result boolValue];

}

-(void)setIsDoing:(BOOL)isDoing

{

           objc_setAssociatedObject(self, &bntExtentIsDoing, @(isDoing), OBJC_ASSOCIATION_RETAIN);

}

@end

   在分类中主要添加了target,actionSelName,isDoing三个属性,target记录响应事件的的处理对象,也就是说当按钮点击后,向那个对象发送按钮点击消息,actionSelName是选择器名称,表示target使用actionSelName代表的选择器对应的方法处理点击事件,isDoing记录是否在处理点击事件,如果在处理点击事件,那么不在处理用户重复点击的事件。

你可能感兴趣的:(按钮猛点,多次响应问题)