美文网首页iOS
UITapGestureRecognizer添加防连点

UITapGestureRecognizer添加防连点

作者: th先生 | 来源:发表于2020-08-13 15:31 被阅读0次

    先说一句,对UIbutton添加全局的防连点,会影响到相机拍照功能。最好是在哪儿需要防连点,在哪儿添加。或者hook一个特定的button类

    最近项目中想加入tap手势的防连点,利用runtime的hook,类似于UIButton.,但是在实际添加中遇到了莫名其妙的问题,绞尽脑汁分析了半天。终于在大牛同事的帮助下,找到了答案!分享给大家。

    首先我按部就班添加UITapGestureRecognizer 的hook方法,其主要代码是hook如下两个方法

    // 将target和action关联到gesture上
    - (instancetype)initTKWithTarget:(id)target action:(SEL)action {
        objc_setAssociatedObject(self, gestureTargetKey, target, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
        objc_setAssociatedObject(self, gestureSelKey, NSStringFromSelector(action), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
        return [self initTKWithTarget:self action:@selector(tkTapAction:)];
    }
    
    - (void)addTKTarget:(id)target action:(SEL)action; {
        [self addTKTarget:self action:@selector(tkTapAction:)];
        objc_setAssociatedObject(self, gestureTargetKey, target, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
        objc_setAssociatedObject(self, gestureSelKey, NSStringFromSelector(action), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    
    

    方法实现

    - (void)tkTapAction:(UITapGestureRecognizer *)tapGesture {
        id target = objc_getAssociatedObject(self, gestureTargetKey);
        SEL action = NSSelectorFromString(objc_getAssociatedObject(self, gestureSelKey));
        
        if (self.eventInterval == 0) {
            self.eventInterval = 3;
        }
        
        if (self.eventUnavailable == NO) {
            self.eventUnavailable = YES;
    
            IMP imp = [target methodForSelector:action];
            void (*func)(id, SEL, UIGestureRecognizer*) = (void*)imp;
            func(target,action,tapGesture);
            
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(self.eventInterval * NSEC_PER_SEC)),
            dispatch_get_main_queue(), ^{
                self.eventUnavailable = NO;
            });
        }
        
    }
    

    那么我遇到的问题是什么呢,就是当我加入这个分类以后,MJRefreshFooter频繁爆出内存泄漏,那么为什么呢?
    MJRefreshAutoStateFooterprepare方法中,有这么一句

    [self.stateLabel addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(stateLabelClick)]];
    
    /** 显示刷新状态的label */
    @property (weak, nonatomic, readonly) UILabel *stateLabel;
    

    这里的stateLabel用weak修饰,添加了手势,引用计数已经+1,随后在我hook方法中,我们采用了OBJC_ASSOCIATION_RETAIN_NONATOMICtarget进行保存,形成了强引用。
    为了解决这个问题,这里采用OBJC_ASSOCIATION_ASSIGN进行修饰就好了。不会对target的引用计数增加。

    如果你遇到其他问题,欢迎留言我们共同进步!

    相关文章

      网友评论

        本文标题:UITapGestureRecognizer添加防连点

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