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 信息就浮動到左上角。 只要繼承就行,不用附加調用代碼, 使用非常簡單。