iOS 無埋點技術(shù)實現(xiàn)

github地址:https://github.com/luojilab/DDAutoTracker-iOS

埋點的重要性

  1. 提高增長率:精準(zhǔn)營銷分析,優(yōu)化推廣效果,改進(jìn)落地頁,提升轉(zhuǎn)化率
  2. 提升用戶活躍度:更細(xì)分的自定義活躍與留存分析,全面提升用戶活躍度
  3. 精準(zhǔn)運營:用戶分群,用戶畫像,多維交叉分析,實現(xiàn)精準(zhǔn)運營
  4. 優(yōu)化產(chǎn)品體驗:通過行為分析,事件分析,漏斗分析,優(yōu)化產(chǎn)品體驗

常見的埋點方式

1. 代碼埋點

通過手寫代碼的方式進(jìn)行埋點。代碼埋點存在高度耦合、依賴發(fā)版、無法動態(tài)更新、容易誤刪、重復(fù)埋點等問題。

2. 無埋點

無埋點方式主要是指不需要代碼埋點,通過app端上報控件信息給埋點配置服務(wù)器,數(shù)據(jù)人員通過上報數(shù)據(jù)進(jìn)行配置埋點信息,然后再下發(fā)給app端,實現(xiàn)無需添加代碼、動態(tài)配置收集用戶使用app的所有事件。

無埋點實現(xiàn)方式

iOS 無埋點方案主要依靠AOP(Aspect Oriented Programming)面向切片編程,通過預(yù)編譯方式和運行期動態(tài)代理針對業(yè)務(wù)處理過程的實體及其屬性和行為進(jìn)行抽象封裝,以獲得更加清晰高效的邏輯單元劃分。

iOS實現(xiàn)AOP編程,主要依賴iOS的runtime機制,method swizzling方法,method swizzling本質(zhì)上就是對IMP(一個函數(shù)指針,保存了方法的地址)和SEL(類成員方法的指針,但不同于C語言中的函數(shù)指針,函數(shù)指針直接保存了方法的地址,但SEL只是方法編號)進(jìn)行交換。

method swizzling是發(fā)生在運行時的,主要用于在運行時將兩個method進(jìn)行交換,我們可以將method swizzling代碼寫到任何地方,但是只有在這段method swizzling碼執(zhí)行完畢之后互換才起作用。

method swizzling原理

在Objective-C中調(diào)用一個方法,其實是向一個對象發(fā)送消息,查找消息的唯一依據(jù)是selector的名字。利用Objective-C的動態(tài)特性,可以實現(xiàn)在運行時偷換selector對應(yīng)的方法實現(xiàn),達(dá)到給方法掛鉤的目的。每個類都有一個方法列表,存放著selector的名字和方法實現(xiàn)的映射關(guān)系。IMP有點類似函數(shù)指針,指向具體的Method實現(xiàn)。


method_swizzling.png

利用method_exchangeImplementations、class_replaceMethod、method_setImplementation等方法偷換selector的IMP。


method_swizzling_2.png

例:

#import <UIKit/UIKit.h>

@interface UIViewController (DDTracker)

@end
#import "UIViewController+DDTracker.h"
#import <objc/runtime.h>

@implementation UIViewController (DDTracker)

+ (void)load {
    Method originalSelector = class_getInstanceMethod(self, @selector(viewWillAppear:));
    Method swizzledSelector = class_getInstanceMethod(self, @selector(swiz_viewWillAppear:));
    method_exchangeImplementations(originalSelector, swizzledSelector);
}

- (void)swiz_viewWillAppear:(BOOL)animated
{
    //在這里填寫需要插入的代碼
    [self sendTrackerData];
    
    //執(zhí)行原來的代碼,不影響代碼邏輯
    [self swiz_viewWillAppear:animated];
}

- (void)sendTrackerData {
    
}

iOS常用UI控件

UIControl

UIControl是UIView的子類,當(dāng)然也是UIResponder的子類。UIControl是諸如UIButton、UISwitch、UITextField等控件的父類,通過endTrackingWithTouch:withEvent:方法可以監(jiān)控UIControl的觸摸事件。

UITableView

UITableView是iOS主要列表控件,通過UITableViewDelegate的tableView:didSelectRowAtIndexPath:方法可以監(jiān)控到UITableView的點擊事件。

UICollectionView

UICollectionView 這個類是iOS6 引進(jìn)的API,它的布局更加靈活,簡單來說就是多列的UITableView,UICollectionView的實現(xiàn)和UITableView的實現(xiàn)基本一樣,也是存在datasource和delegate的,通過UICollectionViewDelegate的collectionView:didSelectItemAtIndexPath:方法可以監(jiān)控到UICollectionView的點擊事件。

UIView

iOS中UIView添加UITapGestureRecognizer手勢實現(xiàn)點擊效果,通過UITapGestureRecognizer的initWithTarget:action:方法可以監(jiān)控到UIView的點擊事件。

事件ID

事件ID的組成主要是通過Viewcontroller(或TableCell)、Class和action通過一定規(guī)則拼接組成。

上報控件信息

當(dāng)用戶點擊控件時,通過runtime運行時在執(zhí)行響應(yīng)方法后,調(diào)用接口,將控件ID以及當(dāng)前class中綁定的數(shù)據(jù)取出來傳給服務(wù)器。

配置信息下拉

[
    {
        "DD_TRACKER_EVENTID_KEY":"DDButtonViewController&&trackerButtonClick:"
    },
    {
        "DD_TRACKER_EVENTID_KEY":"DDTableViewController&&tableView:didSelectRowAtIndexPath:"
    },
    {
        "DD_TRACKER_EVENTID_KEY":"DDCollectionViewController&&collectionView:didSelectItemAtIndexPath:"
    },
    {
        "DD_TRACKER_EVENTID_KEY":"DDGestureViewController&&gestureLabelClick:"
    }
]

上報埋點事件

通過校驗配置信息中的“ DD_TRACKER_EVENTID_KEY”字段來判斷是否發(fā)送打點信息。

使用方法

#import "DDAppDelegate.h"

@implementation DDAppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // Override point for customization after application launch.
 
    //開啟打點
    [[DDAutoTrackerManager sharedInstance] startWithCompletionBlockWithSuccess:^(NSDictionary *trackerDictionary) {
        //成功打點回調(diào)
    } debug:^(NSDictionary *trackerDictionary) {
        //調(diào)試模式回調(diào)
    }];
    //開啟調(diào)試模式
    [DDAutoTrackerManager sharedInstance].isDebug = YES;
    //讀取本地配置文件
    NSString * filePath = [[NSBundle mainBundle] pathForResource:@"tracker" ofType:@"json"];
    NSData * jsonData = [NSData dataWithContentsOfFile:filePath];
    if (jsonData) {
        NSError *error;
        NSArray *jsonArray = [NSJSONSerialization JSONObjectWithData:jsonData options: NSJSONReadingMutableContainers error: &error];
        if (nil == error &&
            jsonArray) {
            [DDAutoTrackerManager sharedInstance].configArray = jsonArray;
        }
    }
    
    return YES;
}

@end

注:建議將"DDAutoTracker.h"引用放在".pch"文件中

數(shù)據(jù)綁定

大多數(shù)情況下,需要綁定一些控件信息。建議使用服務(wù)端返回的數(shù)據(jù)為準(zhǔn)。調(diào)用“configInfoData:”方法配置需要上報的數(shù)據(jù),例:

#import "DDViewController.h"

@interface DDViewController ()

@end

@implementation DDViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.    
    //配置打點info信息
    [self configInfoData:@{@"id":@"your id",
                           @"type":@"your type"}];
}

@end

結(jié)語

通過無埋點方式完成數(shù)據(jù)統(tǒng)計,增加了開發(fā)效率,并保證了數(shù)據(jù)分析的準(zhǔn)確性。Github地址,如果您覺得對您有幫助,請點“star”,謝謝!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容