IOS App 無代碼入侵的方法hook詳細介紹_IOS

來源:互聯網
上載者:User

iOS App 無代碼入侵的方法hook

繼續Objective-C runtime的研究

最近公司項目在做使用者行為分析

於是App端在某些頁面切換,互動操作的時候需要給統計系統發送一條訊息

在幾十個Controller 的項目裡,一個一個地加代碼那完全是不可能的,維護起來也是吃力

但這裡需要處理的是 Controller, 可以有以下方式實現上述需求

1. 利用Objective-C 中的對象繼承

  繼承 在物件導向開發中是非常常用的,像我們現在做的項目工程中都會有一個BaseViewController,

所有建立的ViewController都繼承BaseViewController,通過往BaseViewController中添加一些公用方法\屬性 可以被他們的子類所調用

這是統一我們工程中所有視圖控制器樣式的一個主要途徑

2.利用Category 和Runtime實行方法hook

  hook方案有一個好處,就是可以避免代碼入侵,做到更加廣泛的通用性.通過swizzling我們可以將原method與自己加入的method相結合,

即不需要在原有工程中加入代碼,又能做到全域覆蓋

兩種方案對比:

  通過繼承父類來實現 相對於hook來說 是較為準確的,因為需要被統計的頁面都是繼承於這個父類的控制器,而其他的如UINavigationController,系統內建的UIAlertController等則不會誤入統計資料當中

  上面提到 hook方案是通過hook UIViewController viewdidload/viewdidappear等方法,而這些方法實際上 每個Controller 都會調用,那麼就會出現不該出現的Controller 也出現在這裡(如上面說到的UINavigationController和UIAlertController).但hook方案一個比較好的特點是無代碼入侵,在不修改項目代碼的前提下完成工作.

考慮到 行為分析統計系統 有可能被公司其他項目中所應用,這裡採用hook方案.那麼當中必然會出現 不該統計的卻被統計 的情況,後面再作分析.

既然用到hook方案,又要用runtime 的swizzling

首先 建立一個UIViewController 的category

實現swizzling代碼

+ (void)load{  [super load];    static dispatch_once_t onceToken;  dispatch_once(&onceToken, ^{    // 假如要開啟controller的統計 ,則把下面這行代碼開啟    __gbh_tracer_swizzleMethod([self class], @selector(viewDidAppear:), @selector(__gbh_tracer_viewDidAppear:));  });}

嗯,看到這裡大家會發現 這裡調用的是一個C的方法,然而這個C方法是怎麼實現的呢?看下面

void __gbh_tracer_swizzleMethod(Class class, SEL originalSelector, SEL swizzledSelector){  Method originalMethod = class_getInstanceMethod(class, originalSelector);  Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);    BOOL didAddMethod =  class_addMethod(class,          originalSelector,          method_getImplementation(swizzledMethod),          method_getTypeEncoding(swizzledMethod));    if (didAddMethod) {    class_replaceMethod(class,              swizzledSelector,              method_getImplementation(originalMethod),              method_getTypeEncoding(originalMethod));  } else {    method_exchangeImplementations(originalMethod, swizzledMethod);  }}

這是一個標準的swizzling寫法,當然了 github上面也有關於swizzling的開源庫,用起來也順手 這裡就不多說

看回第一塊代碼,紅色的viewDidAppear是即將被我hook的方法,__gbh_tracer_viewDidAppear 則是我需要實現的方法

- (void)__gbh_tracer_viewDidAppear:(BOOL)animated{  [self __gbh_tracer_viewDidAppear:animated]; //由於方法已經被交換,這裡調用的實際上是viewDidAppear:方法     //設定不允許發送資料的Controller  NSArray *filter = @[@"UINavigationController",@"UITabBarController"];  NSString *className = NSStringFromClass(self.class);  if ([filter containsObject:className]) return ; //如果該Controller在不允許發送log的列表裡,則不能繼續往下走    if ([self.title isKindOfClass:[NSString class]] && self.title.length > 0){ //有標題的才符合我的要求    // 這裡發送log  }}

嗯,剛剛說到有部分Controller我是不發資料的,這裡有兩重判斷,一個是加入到黑名單,另一個是 判斷Controller的title屬性是否為空白

以上判斷基本能滿足我這個行為分析統計系統的需求,若還需要什麼判斷還可以繼續加

以此 我只需要往工程裡面添加這個Category,這個viewDidAppear就會被hook出來,可以為所欲為..

另外 需求中還提到 需要在應用啟動的時候發送一次init訊息

hook?可以,但我更傾向與利用category+NSNotification,因為系統中已經有 UIApplicationDidFinishLaunchingNotification

這種通知,直接用就可以

@implementation UIApplication (GBHTracer)+ (void)load{  [super load];    static dispatch_once_t onceToken;  dispatch_once(&onceToken, ^{ //只執行一次就可以了    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(__gbh_tracer_applicationDidFinishLaunching:) name:UIApplicationDidFinishLaunchingNotification object:nil];  });}+ (void)__gbh_tracer_applicationDidFinishLaunching:(NSNotification *)noti{  //應用啟動時為所欲為!}@end

嗯..我們的行為分析統計系統就在原工程不Import一個標頭檔 不調用 任何一個方法就可以達到統計效果.

但是像什麼操作響應的時候的統計,還是需要各位看官在響應中調用相應的方法

感謝閱讀,希望能協助到大家,謝謝大家對本站的支援!

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.