美文网首页
iOS开发:避免按钮短时间内多次响应同一种方法

iOS开发:避免按钮短时间内多次响应同一种方法

作者: 抄无止境 | 来源:发表于2018-09-04 13:50 被阅读111次

    解决办法

    1.在每次点击时先取消之前的操作

    - (void)cancelBtnAction:(UIButton *)btn {
        
        [[self class] cancelPreviousPerformRequestsWithTarget:self selector:@selector(toDoSomething:) object: btn];
        [self performSelector:@selector(toDoSomething:)withObject:btn afterDelay: 0.2f];
    }
    
    - (void)toDoSomething:(UIButton *)btn {
        
        NSLog(@"在每次点击时先取消之前的操作");
    }
    

    2.点击一次后将button的enabled变为NO。在适当的地方把enabled变为YES

    3.用Runtime监听点击事件,忽略重复点击,使其规定时间内只响应一次点击事件

    • 为按钮添加多个target方法
    //测试本方法之前记得把runtime注释打开
        [testBtn setTitle:@"Runtime防止重复响应事件" forState:UIControlStateNormal];
        [testBtn addTarget:self action:@selector(testBtn:) forControlEvents:UIControlEventTouchUpInside];
        [testBtn addTarget:self action:@selector(testBtnTouchDown:) forControlEvents:UIControlEventTouchDown];
        [testBtn addTarget:self action:@selector(testBtnTouchUpOutside:) forControlEvents:UIControlEventTouchUpOutside];
        testBtn.eventTimeInterval = 2;
    

    解释一下为什么要添加多个target:如果我们不区分target触发的方法,那么一个按钮同时设置多个target,就会出现_wxd_sendAction:to:forEvent:event执行多次,只而触发了一个target,具体触发的是哪个自己试验

    • 在UIButton类目中加入属性
    @interface UIButton (Leon)
    //  为按钮添加点击间隔 eventTimeInterval秒
    @property (nonatomic, assign) NSTimeInterval eventTimeInterval;
    @end
    
    @interface UIButton ()
    
    /*
     ***key:方法的名字
     ***value:是否在eventTimeInterval秒内重复点击
     ***问题描述:如果按钮只增加了一个addTarget:action:forControlEvents:网络上的实现方案是没有问题的,如果一个按钮btn增加多个addTarget:action:forControlEvents:方法,则网络上那个就不能实现,这个我做了改版
     ***适用于:同一个按钮,增加了多个addTarget:action:forControlEvents:方法,方法名字必须不同(不然会出现bug)
     ***不完善处:如果能获得是哪种UIControlEvents点击事件,根据那个点击事件来作为ignoreEventDic字典的key才能准确防止同一个按钮,不同的点击事件,来达成防止重复点击的效果
     */
    @property (nonatomic, strong) NSMutableDictionary *ignoreEventDic;
    @end
    
    • 然后进行方法的交换
    + (void)load {
        // Method Swizzling
        [self swizzleMethod:@selector(sendAction:to:forEvent:) withMethod:@selector(_wxd_sendAction:to:forEvent:) error:nil];
    }
    
    - (void)_wxd_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event {
        
        if (!self.ignoreEventDic) {
            self.ignoreEventDic = [NSMutableDictionary dictionaryWithCapacity:1];
        }
        self.eventTimeInterval = self.eventTimeInterval == 0 ? defaultInterval : self.eventTimeInterval;
        if ([[self.ignoreEventDic objectForKey:NSStringFromSelector(action)] isEqualToString:@"1"]){
            return;
        } else if (self.eventTimeInterval > 0){
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(self.eventTimeInterval * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                [self.ignoreEventDic setObject:@"0" forKey:NSStringFromSelector(action)];
            });
        }
        
        [self.ignoreEventDic setObject:@"1" forKey:NSStringFromSelector(action)];
        // 这里看上去会陷入递归调用死循环,但在运行期此方法是和sendAction:to:forEvent:互换的,相当于执行sendAction:to:forEvent:方法,所以并不会陷入死循环。
        [self _wxd_sendAction:action to:target forEvent:event];
    }
    

    文章是根据前人肩膀上完成,类似的文章很多,自己的总是显得更加完善
    有什么不足之处麻烦留言,必改.

    相关文章

      网友评论

          本文标题:iOS开发:避免按钮短时间内多次响应同一种方法

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