美文网首页
Runtime统计按钮点击次数-2021-02-25-周四

Runtime统计按钮点击次数-2021-02-25-周四

作者: 勇往直前888 | 来源:发表于2021-03-02 16:30 被阅读0次

    需要统计按钮的统计数据,怎么实现?
    当然现实开发中可以用友盟统计,很方便很强大;
    如果用自定义的按钮,那么在一个地方统一写一下,也很方便;
    如果用UIButton,自己实现呢?
    当然是用runtimecategory来实现。

    按钮分类

    • UIButton的分类添加两个属性,一个是记忆点击次数,一个是保存按钮响应的action
    @interface UIButton (ClickCount)
    
    // 点击次数
    @property (assign, nonatomic) NSInteger clickCount;
    
    // 点击响应
    @property (copy, nonatomic) void(^currentActionBlock)(void);
    
    @end
    
    • 由于是分类添加属性,所以要用到runtime中关联对象相关的部分
    // 关联对象的key
    static NSString *clickCountKey = @"clickCount";
    static NSString *currentActionBlockKey = @"currentActionBlock";
    
    // setter/getter
    // 点击次数
    - (void)setClickCount:(NSInteger)clickCount {
        objc_setAssociatedObject(self, &clickCountKey, @(clickCount), OBJC_ASSOCIATION_ASSIGN);
    }
    
    - (NSInteger)clickCount {
        NSNumber *clickCountValue = objc_getAssociatedObject(self, &clickCountKey);
        return clickCountValue.integerValue;
    }
    
    // 点击响应
    - (void)setCurrentActionBlock:(void (^)(void))currentActionBlock {
        objc_setAssociatedObject(self, &currentActionBlockKey, currentActionBlock, OBJC_ASSOCIATION_COPY_NONATOMIC);
    }
    
    - (void (^)(void))currentActionBlock {
        return objc_getAssociatedObject(self, &currentActionBlockKey);
    }
    
    • 由于要添加按钮点击次数,所以要替换系统方法- (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents
    + (void)load {
        // 方法替换;用自定义的点击响应替换系统的点击响应
        // 只能交换一次
        static dispatch_once_t onceToken;
            dispatch_once(&onceToken, ^{
                
                SEL origilaSEL = @selector(addTarget: action: forControlEvents:);
                
                SEL hook_SEL = @selector(xw_addTarget: action: forControlEvents:);
                
                //交换方法
                Method origilalMethod = class_getInstanceMethod(self, origilaSEL);
                
                
                Method hook_method = class_getInstanceMethod(self, hook_SEL);
                
                
                class_addMethod(self,
                                origilaSEL,
                                class_getMethodImplementation(self, origilaSEL),
                                method_getTypeEncoding(origilalMethod));
                
                class_addMethod(self,
                                hook_SEL,
                                class_getMethodImplementation(self, hook_SEL),
                                method_getTypeEncoding(hook_method));
                
                method_exchangeImplementations(class_getInstanceMethod(self, origilaSEL), class_getInstanceMethod(self, hook_SEL));
                
            });
    }
    
    // 替换的方法,
    - (void)xw_addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents {
        
        __weak typeof(target) weakTarget = target;
        __weak typeof(self) weakSelf = self;
    
        if (action) {
            self.currentActionBlock = ^{
                @try {
                    ((void (*)(void *, SEL,  typeof(weakSelf) ))objc_msgSend)((__bridge void *)(weakTarget), action , weakSelf);
                } @catch (NSException *exception) {
                } @finally {
                }
            };
        }
        
        //发送消息 其实是本身  要执行的action 先执行,写下来的 xw_clicked:方法
        [self xw_addTarget:self action:@selector(xw_clicked:) forControlEvents:controlEvents];
    }
    
    //拦截了按钮点击后要执行的代码
    - (void)xw_clicked:(UIButton *)sender{
        //统计 在这个方法中执行想要操作的
        self.clickCount++;
        
        NSLog(@"%@ 点击 %ld次 ",[sender titleForState:UIControlStateNormal], self.clickCount);
        
        //执行原来要执行的方法
        sender.currentActionBlock();
    }
    

    测试界面

    image.png

    参考文章

    iOS统计整个App 每个按钮的点击次数

    ClickCountOfButton

    Demo地址

    RuntimeDemo

    相关文章

      网友评论

          本文标题:Runtime统计按钮点击次数-2021-02-25-周四

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