一款iOS UITableView, UICollectionView 曝光埋点框架LBTrackManager,支持有效曝光,数据去重,可扩展 .支持pod

列表曝光埋点框架

埋点时机

我这里 在滚动停止埋点(这种停止滚动时候埋点暂且称为无效点),
开始拖动埋点(这时候通过判断拖动之前停留的时间长短来确定是否埋点)
框架hook 了三个 系统方法

  • (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView

  • (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate

  • (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView

核心代码

/// tableView滑动停止
/// @param options hook类型
+ (void)track_tableViewImpression_scrollViewDidEndDecelerating:(AspectOptions)options
                                                     presenter:(NSObject *)presenter;
{
    NSError *error = nil;
    [presenter aspect_hookSelector:@selector(scrollViewDidEndDecelerating:) withOptions:options usingBlock:^(id<AspectInfo> data){
        UITableView *tableView = [data arguments].firstObject;
        NSDate* date = [NSDate dateWithTimeIntervalSinceNow:0];//获取当前时间0秒后的时间
        NSTimeInterval time = [date timeIntervalSince1970]*1000;//
        tableView.preScrollEndTime = time;
        NSMutableArray *cellsArray = [self unEffectiveCellArrayWithTableView:tableView];
        [helper unEffectiveImpressionWithTableViewCellArray:cellsArray];
    } error:&error];
}

///拖动停止, 这里需要注意,要在不减速的情况先
+ (void)track_tableViewImpression_scrollViewDidEndDragging:(AspectOptions)options
                                                 presenter:(NSObject *)presenter;
{
    NSError *error = nil;
    [(NSObject *)presenter aspect_hookSelector:@selector(scrollViewDidEndDragging:willDecelerate:) withOptions:options usingBlock:^(id<AspectInfo> data){
        UITableView *tableView = [data arguments].firstObject;
        
        BOOL decelerate = [[data arguments].lastObject boolValue];
        if (!decelerate) {
            NSMutableArray *cellsArray = [self unEffectiveCellArrayWithTableView:tableView];
            NSDate* date = [NSDate dateWithTimeIntervalSinceNow:0];//获取当前时间0秒后的时间
            NSTimeInterval time = [date timeIntervalSince1970]*1000;//
            tableView.preScrollEndTime = time;
            [helper unEffectiveImpressionWithTableViewCellArray:cellsArray];
        }
    } error:&error];
}

///开始拖动, 进行埋有效点
+ (void)track_tableViewImpression_scrollViewBeginDragging:(AspectOptions)options
                                                 delegate:(NSObject *)delegate
{
    NSError *error = nil;
    [(NSObject *)delegate aspect_hookSelector:@selector(scrollViewWillBeginDragging:) withOptions:options usingBlock:^(id<AspectInfo> data){
        UITableView *tableView = [data arguments].firstObject;
        NSDate* date = [NSDate dateWithTimeIntervalSinceNow:0];//获取当前时间0秒后的时间
        NSTimeInterval time = [date timeIntervalSince1970]*1000;//
        if (time - tableView.preScrollEndTime > effectiveTimeThreshhold) {
            ///时间差大于阈值,才进行有效曝光埋点
            [helper effectiveImpressionWithTableViewCellArray:tableView.preEffectiveCellsArray];
        }
    } error:&error];
    
}


获取当前展示cell

/*注意:我们是通过CGRectContainsRect(tableView.bounds, 
来判断cell是否完全在tableView中的*/
+ (NSMutableArray <UITableViewCell *> *)cellArrayWithTableView:(UITableView *)tableView
{
    NSMutableArray *cellsArray = [NSMutableArray new];

    for (UITableViewCell *cell in tableView.visibleCells) {
        BOOL isRealShow = CGRectContainsRect(tableView.bounds, cell.frame);
        if (!isRealShow) {
            continue;
        }
        [cellsArray addObject:cell];
    }
    return cellsArray;
}

数据去重

我这里给tableView 绑定了 preEndScrollCellsArray属性,用来记录上次停止的时候展示的cell, 和这次停止的对比,做数据去重
/*
记录上次滚动停止的时候展示的cell indexpath数组,和现在停止时候
cell的indexPath数组对比,用来做数据去重
*/

@property (nonatomic, strong) NSArray *preEndScrollCellsArray;

/*
记录上次开始滚动时候有效曝光数组,和现在开始拖动cell
的indexPath数组对比,用来做数据去重
*/
@property (nonatomic, strong) NSArray *preEffectiveCellsArray;

核心代码

+ (NSMutableArray <NSIndexPath *> *)unEffectiveCellArrayWithTableView:(UITableView *)tableView
{
    NSMutableArray *cellsArray = [self cellArrayWithTableView:tableView];
    NSMutableArray *preEndScrollIndexPathsArray = [NSMutableArray array];
    NSMutableArray *preEffectiveIndexPathsArray = [NSMutableArray array];
    [cellsArray enumerateObjectsUsingBlock:^(UITableViewCell * obj, NSUInteger idx, BOOL * _Nonnull stop) {
        /*数据去重, 这里使用indexpath 对比进行去重,没有直接使用cell, 因为
         cell涉及到重用,直接用cell来比较不准确
        */
        NSIndexPath *cellIndexPath = [tableView indexPathForCell:obj];
        __block BOOL hasBeenInPreIndexPathArray = NO;
        [tableView.preEndScrollCellsArray enumerateObjectsUsingBlock:^(NSIndexPath *preIndex, NSUInteger idx, BOOL * _Nonnull stop) {
            if (cellIndexPath.row == preIndex.row &&
                 cellIndexPath.section == preIndex.section) {
                hasBeenInPreIndexPathArray = YES;
            }
        }];
        if (!hasBeenInPreIndexPathArray) {
            [preEffectiveIndexPathsArray addObject:cellIndexPath];
        } 
        [preEndScrollIndexPathsArray addObject:cellIndexPath];
    }];
    tableView.preEffectiveCellsArray = preEffectiveIndexPathsArray;
    tableView.preEndScrollCellsArray = preEndScrollIndexPathsArray;
    return preEffectiveIndexPathsArray;
}

使用方法

pod ‘LBTrackManager’

创建埋点helper继承于 LBTrackHelper

@interface LBSubTrackHelper : LBTrackHelper

@end

重写 - (void)unEffectiveImpressionWithTableView:(UITableView *)tableView
cellIndexPathsArray:(NSArray<NSIndexPath *> *)array 和- (void)effectiveImpressionWithTableView:(UITableView *)tableView
cellIndexPathsArray:(NSArray<NSIndexPath *> *)array两个方法 实现埋点,这里我只做一个示例,打印展示的cell

@implementation LBSubTrackHelper

- (void)unEffectiveImpressionWithTableView:(UITableView *)tableView
                       cellIndexPathsArray:(NSArray<NSIndexPath *> *)array
{
    [array enumerateObjectsUsingBlock:^(NSIndexPath * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        NSLog(@"展示的内容内容%ld",obj.row);
    }];
}

- (void)effectiveImpressionWithTableView:(UITableView *)tableView
                     cellIndexPathsArray:(NSArray<NSIndexPath *> *)array
{
    [array enumerateObjectsUsingBlock:^(NSIndexPath * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        NSLog(@"有效曝光有效曝光展示的内容内容%ld",obj.row);
    }];
}

@end

app启动的时候 配置helper

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    LBSubTrackHelper *helper = [[LBSubTrackHelper alloc] init];
    [LBTrackManager configTrackHelper:helper];
    // Override point for customization after application launch.
    return YES;
}

在某个需要埋点的页面注册tableView即可

    [LBTrackManager trackRegisterTableView:self.tableView tableViewDelegate:self];

如下图,是我测试的效果,准确的获取了滚动停止的cell
请添加图片描述

接着再次滚动(上次是曝光到第12条),查看展示内容,已经去重
请添加图片描述

demo

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值