UITapGestureRecognizer添加防连点

先说一句,对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添加防连点)