先说一句,对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频繁爆出内存泄漏,那么为什么呢?
在MJRefreshAutoStateFooter
的prepare
方法中,有这么一句
[self.stateLabel addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(stateLabelClick)]];
/** 显示刷新状态的label */
@property (weak, nonatomic, readonly) UILabel *stateLabel;
这里的stateLabel用weak
修饰,添加了手势,引用计数已经+1,随后在我hook方法中,我们采用了OBJC_ASSOCIATION_RETAIN_NONATOMIC
对target
进行保存,形成了强引用。
为了解决这个问题,这里采用OBJC_ASSOCIATION_ASSIGN
进行修饰就好了。不会对target
的引用计数增加。
如果你遇到其他问题,欢迎留言我们共同进步!
网友评论