IOS運行時Method Swizzling (2)

前言

上一篇簡單介紹了一下通過運行時添加方法延欠。這篇文章呢,側(cè)重于方法的hook。

Method Swizzling 原理

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


1.png

利用運行時的一些方法育勺,我們可以做到對系統(tǒng)原有方法的hook,也叫method swizzling。


2.png

實例舉例

最近在項目中接入了友盟的數(shù)據(jù)統(tǒng)計罗岖,其中有一個功能涧至,可以統(tǒng)計app各個頁面的打開次數(shù),時間等呀闻。

實現(xiàn)頁面的統(tǒng)計需要在每個View中配對調(diào)用如下方法:
- (void)viewWillAppear:(BOOL)animated { 
[super viewWillAppear:animated]; 
[MobClick beginLogPageView:@"PageOne"];//("PageOne"為頁面名稱化借,可自定義) 
}
- (void)viewWillDisappear:(BOOL)animated { 
[super viewWillDisappear:animated]; 
[MobClick endLogPageView:@"PageOne"];
 }

就像文檔描述的,我們需要在生命周期函數(shù)中添加語句捡多,但由于目前項目已經(jīng)基本穩(wěn)定蓖康,因此一個頁面一個頁面的改,難免費時費力垒手。于是考慮AOP蒜焊,直接hook掉這些函數(shù)。

//demo
#import <objc/runtime.h>
 
@implementation UIViewController (Tracking)
 
+ (void)load {
        static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class class = [self class];         
        // When swizzling a class method, use the following:
       // Class class = object_getClass((id)self);
 
        SEL originalSelector = @selector(viewWillAppear:);
                    SEL swizzledSelector = @selector(xxx_viewWillAppear:);
 
        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);
        }
    });
}
 
#pragma mark - Method Swizzling
 
- (void)xxx_viewWillAppear:(BOOL)animated {
        [self xxx_viewWillAppear:animated];
    NSLog(@"viewWillAppear: %@", self);
}
 
@end

選擇器科贬、方法與實現(xiàn)

在Objective-C中泳梆,選擇器(selector)、方法(method)和實現(xiàn)(implementation)是運行時中一個特殊點榜掌,雖然在一般情況下优妙,這些術(shù)語更多的是用在消息發(fā)送的過程描述中。

以下是Objective-C Runtime Reference中的對這幾個術(shù)語一些描述:

Selector(typedef struct objc_selector *SEL):用于在運行時中表示一個方法的名稱憎账。一個方法選擇器是一個C字符串套硼,它是在Objective-C運行時被注冊的。選擇器由編譯器生成胞皱,并且在類被加載時由運行時自動做映射操作邪意。
Method(typedef struct objc_method Method):在類定義中表示方法的類型
Implementation(typedef id (
IMP)(id, SEL, …)):這是一個指針類型,指向方法實現(xiàn)函數(shù)的開始位置反砌。這個函數(shù)使用為當前CPU架構(gòu)實現(xiàn)的標準C調(diào)用規(guī)范雾鬼。第一個參數(shù)是指向?qū)ο笞陨淼闹羔?self),第二個參數(shù)是方法選擇器宴树。然后是方法的實際參數(shù)策菜。
理解這幾個術(shù)語之間的關(guān)系最好的方式是:一個類維護一個運行時可接收的消息分發(fā)表;分發(fā)表中的每個入口是一個方法(Method),其中key是一個特定名稱做入,即選擇器(SEL)冒晰,其對應(yīng)一個實現(xiàn)(IMP)同衣,即指向底層C函數(shù)的指針竟块。

為了swizzle一個方法,我們可以在分發(fā)表中將一個方法的現(xiàn)有的選擇器映射到不同的實現(xiàn)耐齐,而將該選擇器對應(yīng)的原始實現(xiàn)關(guān)聯(lián)到一個新的選擇器中浪秘。

參考

Objective-C Runtime 運行時之四:Method Swizzling
iOS黑魔法-Method Swizzling

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市埠况,隨后出現(xiàn)的幾起案子耸携,更是在濱河造成了極大的恐慌,老刑警劉巖辕翰,帶你破解...
    沈念sama閱讀 218,036評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件夺衍,死亡現(xiàn)場離奇詭異,居然都是意外死亡喜命,警方通過查閱死者的電腦和手機沟沙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來壁榕,“玉大人矛紫,你說我怎么就攤上這事∨评铮” “怎么了颊咬?”我有些...
    開封第一講書人閱讀 164,411評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長牡辽。 經(jīng)常有香客問我喳篇,道長,這世上最難降的妖魔是什么态辛? 我笑而不...
    開封第一講書人閱讀 58,622評論 1 293
  • 正文 為了忘掉前任麸澜,我火速辦了婚禮,結(jié)果婚禮上因妙,老公的妹妹穿的比我還像新娘痰憎。我一直安慰自己,他們只是感情好攀涵,可當我...
    茶點故事閱讀 67,661評論 6 392
  • 文/花漫 我一把揭開白布铣耘。 她就那樣靜靜地躺著,像睡著了一般以故。 火紅的嫁衣襯著肌膚如雪蜗细。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,521評論 1 304
  • 那天,我揣著相機與錄音炉媒,去河邊找鬼踪区。 笑死,一個胖子當著我的面吹牛吊骤,可吹牛的內(nèi)容都是我干的缎岗。 我是一名探鬼主播,決...
    沈念sama閱讀 40,288評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼白粉,長吁一口氣:“原來是場噩夢啊……” “哼传泊!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起鸭巴,我...
    開封第一講書人閱讀 39,200評論 0 276
  • 序言:老撾萬榮一對情侶失蹤眷细,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后鹃祖,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體溪椎,經(jīng)...
    沈念sama閱讀 45,644評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,837評論 3 336
  • 正文 我和宋清朗相戀三年恬口,在試婚紗的時候發(fā)現(xiàn)自己被綠了校读。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,953評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡楷兽,死狀恐怖地熄,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情芯杀,我是刑警寧澤端考,帶...
    沈念sama閱讀 35,673評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站揭厚,受9級特大地震影響却特,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜筛圆,卻給世界環(huán)境...
    茶點故事閱讀 41,281評論 3 329
  • 文/蒙蒙 一裂明、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧太援,春花似錦闽晦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至碱蒙,卻和暖如春荠瘪,著一層夾襖步出監(jiān)牢的瞬間夯巷,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評論 1 269
  • 我被黑心中介騙來泰國打工哀墓, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留趁餐,地道東北人。 一個月前我還...
    沈念sama閱讀 48,119評論 3 370
  • 正文 我出身青樓篮绰,卻偏偏與公主長得像后雷,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子阶牍,可洞房花燭夜當晚...
    茶點故事閱讀 44,901評論 2 355

推薦閱讀更多精彩內(nèi)容