1. 程式人生 > >iOS App 無程式碼入侵的方法hook

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一個頭檔案 不呼叫 任何一個方法就可以達到統計效果.

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

相關推薦

iOS App 程式碼入侵方法hook

繼續Objective-C runtime的研究 最近公司專案在做使用者行為分析 於是App端在某些頁面切換,互動操作的時候需要給統計系統傳送一條訊息 在幾十個Controller 的專案裡,一個一個地加程式碼那完全是不可能的,維護起來也是吃力 但這裡需要處理的是 Controller, 可以有以下方式實現上

CLANG技術分享系列四:IOS APP無用程式碼/重複程式碼分析

01 NOV 2016 . CATEGORY: TECH . COMMENTS #CLANG 問題背景 包瘦身,包瘦身,包瘦身,重要的事情說三遍。 最近公司一款APP一直在瘦身,我們團隊的APP也愈發龐大了。就想看看除過資

iOS App Store 上傳專案報 隱私政策網址(URL)!~解決方法

    聯絡人:石虎 QQ:1224614774   暱稱: 嗡嘛呢叭咪哄                       &

IOS —— App啟動原理及程式碼優化

哈嘍,好久不見。最近處於心情低迷期就沒怎麼來更新文章了。 在下也算是個半路出家的程式碼家,從之前的文章更新到現在 依然是還是從基礎學起,萬物歸基礎! 所以從今天起每天回來更新彙報學習成果!!每天 今天主要接觸的是Application相關的知識,包括App啟動原理,以及windos視窗控制以及Appd

iOS App Store 上傳專案報 隱私政策網址(URL)!~解決方法

    聯絡人:石虎 QQ:1224614774   暱稱: 嗡嘛呢叭咪哄                          QQ群:807236138   群稱: iOS 技術交流學習群 一、

大話西遊手遊蘋果ios退款流程 蘋果app應用商店退款方法

IOS蘋果退款失敗了還能退嗎?這個的話我是不敢保證的,一個賬號有很多因素會影響成功率.我也不能保證百分之百能給大家挽回損失.不過我會盡全力去幫助大家.不過就算id被拉黑沒有退款資格,也不用擔心.我這裡會為大家講講如何去養好一個ID 蘋果系統針對蘋果使用者的一項政

SAP SMP kapsel iOS app編譯方法

以SMP 3.0 SDK SP12為例 =========================== 安裝node node -v =========================== 安裝cordova npm uninstall cordova -g

iOS 給測試人員測試手機APP的四種方法:真機執行(略),打ipa包,(testFlighe)郵件,蒲公英(一)打ipa包

APP上線前測試,無外乎 一:用資料線真機除錯(以前需要下載真機除錯證書) 二:打.ipa包給測試人員(上限100人)     2.1 打包APP的.ipa 包給測試人員之前,如果沒有新增裝置的UDID號, 先進入蘋果開發者中心(添加了直接跳到2.6)  2.2點

iOS替換方法hook

HOOK + (void)load {     SEL origSel = @selector(viewDidAppear:);     SEL swizSel = @selector(swiz_v

iOS 0 行程式碼系列】之 0 行程式碼實現TableView,CollectionView資料佔位圖與文字

如果你還沒有看過下面的文章,可以花點時間看看 >>>>>1.一行程式碼完成“空TableView佔位檢視”管理: 原理: 1.獲取 Section 的數量 2.

iOS App Archive 版本出錯的問題 除錯和解決方法

現象: debug聯機除錯時無問題archive出來安裝到iPhone執行報錯 聯機在organizer中看錯誤日誌: Triggered by Thread:  0Thread 0 Crashed:0   SanguoOnline                    

iOS app生命週期方法執行探究

使用一個新建立的沒有後臺執行的app測試: [LogInfo] 2018-11-06 10:49:25.444 File:AppDelegate Line:30 Function:-[AppDelegate applicationWillResignActive

ios app上傳成功但ITunes Connect不顯示的解決方法

使用Xcode或Application Loader上傳顯示成功,但是在ITunes Connect正在處理之後就沒了。這個時候不要改build傳了,只需要在info.plist加上對應的隱私描述就行了 從iOS10開始,蘋果更加註重對用於隱私的保護,

ios app退出後cookies丟失的解決方法

前兩天我在做uiwebview通過cookies自動登入的時候,發現app退出後cookies丟失,搞了一天找不出原因,最後發現ios的cookies需要程式設計師手動設定儲存時間,預設下,cookies的儲存時間是app退出後cookie就會被清掉! 怎麼儲存呢?簡單得讓

IOS app電量測試方法調研

方法一——硬體檢測通過硬體 PowerMonitor 可以精準地獲得應用的電量消耗。步驟如下:拆開iOS裝置的外殼,找到電池後面的電源針腳。連線電源監控器的裝置針腳執行應用測量電量消耗下圖展示了與iPhone的電池針腳連線的電源監控器工具。enter image descri

改變iOS app的icon(iOS10.3)

res sta play type assets icon stand wss 桌面 原文 改變iOS app的icon官方iOS10.3新增了可以讓開發者去更改app的icon,接下來看看怎麽更改。官方API給的東西很少,只是介紹了一個實例方法: 1

iOS app內打開safari

blank googl ppa git cnblogs afa http oauth 允許 最近使用google的oauth認證,發現不再允許使用UIWebview進行認證了,必須使用系統遊覽器,使用遊覽器也不一定要在app之間跳轉,ios使用SFSafariViewCon

iOS App初次啟動時的用戶引導頁制作實例分享

復制代碼 bound gpo 並且 fault launch boa com content iOS App初次啟動時的用戶引導頁制作實例分享 作者:老初 字體:[增加 減小] 類型:轉載 時間:2016-03-09 我要評論 這篇文章主要介紹了iOS App初次啟動

ios App 動畫分享

and tab ios ebo *** fadein car ble check 一、動畫分享 1. ************* 轉場動畫 *************    ZFDragableModalTransition    GTAppMenuContro

ios App textField placeholder 信息上浮

ext label desc setup utl per loading idt atomic textField placeholder 提示信息上浮 當輸入框 有文的時候 placeholder 信息就浮動到左上角。 只要繼承就行,不用附加調用代碼, 使用非常簡單。