Runtime之Method Swizzling

Runtime 又叫運行時,iOS 內(nèi)部的核心之一,底層的 為C 語言 寫的API,底層都是基于它來實現(xiàn)的筏勒。在沒有一個類的實現(xiàn)源碼的情況下男公,想改變其中一個方法的實現(xiàn)千所,除了繼承它重寫、和借助類別重名方法暴力搶先之外吮播,還有更加靈活的方法嗎鹰服?那就是Method Swizzling病瞳,利用運行時優(yōu)雅地實現(xiàn)。

一悲酷、說到Method Swizzling先提到幾個概念:

SEL:它是selector在 Objc 中的表示(Swift 中是 Selector 類)套菜。selector 是方法選擇器,其實作用就和名字一樣设易,日常生活中逗柴,我們通過人名辨別誰是誰,注意 Objc 在相同的類中不會有命名相同的兩個方法顿肺。selector 對方法名進行包裝戏溺,以便找到對應(yīng)的方法實現(xiàn)。它的數(shù)據(jù)結(jié)構(gòu)是:

typedefstruct objc_selector *SEL;

IMP

IMP實際上是一個函數(shù)指針屠尊,指向方法實現(xiàn)的地址旷祸。

其定義如下:

id (*IMP)(id, SEL,...)

Method:Method 代表類中某個方法的類型

typedefstruct objc_method *Method;struct objc_method {

SEL method_name

OBJC2_UNAVAILABLE;char *method_types

OBJC2_UNAVAILABLE;

IMP method_imp

OBJC2_UNAVAILABLE;}

objc_method存儲了方法名,方法類型和方法實現(xiàn):

方法名類型為SEL

方法類型method_types是個 char 指針讼昆,存儲方法的參數(shù)類型和返回值類型

method_imp指向了方法的實現(xiàn)托享,本質(zhì)是一個函數(shù)指針

二、Method Swizzling原理

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

而且Method Swizzling也是iOS中AOP(面相切面編程)的一種實現(xiàn)方式羡榴,我們可以利用蘋果這一特性來實現(xiàn)AOP編程碧查。

首先,讓我們通過兩張圖片來了解一下Method Swizzling的實現(xiàn)原理

圖一

圖二

上面圖一中selector2原本對應(yīng)著IMP2校仑,但是為了更方便的實現(xiàn)特定業(yè)務(wù)需求么夫,我們在圖二中添加了selector3和IMP3,并且讓selector2指向了IMP3肤视,而selector3則指向了IMP2,這樣就實現(xiàn)了“方法互換”涉枫。

在OC語言的runtime特性中邢滑,調(diào)用一個對象的方法就是給這個對象發(fā)送消息。是通過查找接收消息對象的方法列表愿汰,從方法列表中查找對應(yīng)的SEL困后,這個SEL對應(yīng)著一個IMP(一個IMP可以對應(yīng)多個SEL),通過這個IMP找到對應(yīng)的方法調(diào)用衬廷。

在每個類中都有一個Dispatch Table摇予,這個Dispatch Table本質(zhì)是將類中的SEL和IMP(可以理解為函數(shù)指針)進行對應(yīng)。而我們的Method Swizzling就是對這個table進行了操作吗跋,讓SEL對應(yīng)另一個IMP侧戴。

三、Method Swizzling實現(xiàn)

在實現(xiàn)Method Swizzling時跌宛,核心代碼主要就是一個runtime的C語言API:

OBJC_EXPORT void method_exchangeImplementations(Method m1, Method m2)

__OSX_AVAILABLE_STARTING(__MAC_10_5,?__IPHONE_2_0);

而 Method Swizzling 可以交換兩個方法的IMP酗宋。你可以重寫某個方法而不用繼承,同時還可以調(diào)用原先的實現(xiàn)疆拘。通常的做法是在category中添加一個方法(當(dāng)然也可以是一個全新的class)蜕猫。可以通過method_exchangeImplementations這個運行時方法來交換實現(xiàn)哎迄。來看一個demo回右,這個demo演示了如何重寫addObject:方法來紀錄每一個新添加的對象。

#import <objc/runtime.h>

@interface NSMutableArray (LoggingAddObject)

- (void)logAddObject:(id)aObject;

@end

@implementation NSMutableArray (LoggingAddObject)

+ (void)load {

Method addobject = class_getInstanceMethod(self, @selector(addObject:));

Method logAddobject = class_getInstanceMethod(self, @selector(logAddObject:));

method_exchangeImplementations(addObject, logAddObject);

}

- (void)logAddObject:(id)aobject {

[self logAddObject:aObject];

NSLog(@"Added object %@ to array %@", aObject, self);

}

@end

我們把方法交換放到了load中漱挚,這個方法只會被調(diào)用一次翔烁,而且是運行時載入。如果指向臨時用一下棱烂,可以放到別的地方租漂。注意到一個很明顯的遞歸調(diào)用logAddObject:。這也是Method Swizzling容易把我們搞混的地方,因為我們已經(jīng)交換了方法的實現(xiàn)哩治,所以其實調(diào)用的是addObject:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末秃踩,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子业筏,更是在濱河造成了極大的恐慌憔杨,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蒜胖,死亡現(xiàn)場離奇詭異消别,居然都是意外死亡,警方通過查閱死者的電腦和手機台谢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進店門寻狂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人朋沮,你說我怎么就攤上這事蛇券。” “怎么了樊拓?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵纠亚,是天一觀的道長。 經(jīng)常有香客問我筋夏,道長蒂胞,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任条篷,我火速辦了婚禮骗随,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘赴叹。我一直安慰自己蚊锹,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布稚瘾。 她就那樣靜靜地躺著牡昆,像睡著了一般。 火紅的嫁衣襯著肌膚如雪摊欠。 梳的紋絲不亂的頭發(fā)上丢烘,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天,我揣著相機與錄音些椒,去河邊找鬼播瞳。 笑死,一個胖子當(dāng)著我的面吹牛免糕,可吹牛的內(nèi)容都是我干的赢乓。 我是一名探鬼主播忧侧,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼牌芋!你這毒婦竟也來了蚓炬?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤躺屁,失蹤者是張志新(化名)和其女友劉穎肯夏,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體犀暑,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡驯击,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了耐亏。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片徊都。...
    茶點故事閱讀 40,675評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖广辰,靈堂內(nèi)的尸體忽然破棺而出碟贾,到底是詐尸還是另有隱情,我是刑警寧澤轨域,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站干发,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏史翘。R本人自食惡果不足惜枉长,卻給世界環(huán)境...
    茶點故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望琼讽。 院中可真熱鬧必峰,春花似錦、人聲如沸钻蹬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽问欠。三九已至肝匆,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間顺献,已是汗流浹背旗国。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留注整,地道東北人能曾。 一個月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓度硝,卻偏偏與公主長得像,于是被迫代替她去往敵國和親寿冕。 傳聞我的和親對象是個殘疾皇子蕊程,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,685評論 2 360

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

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,726評論 0 9
  • 我們常常會聽說 Objective-C 是一門動態(tài)語言蚂斤,那么這個「動態(tài)」表現(xiàn)在哪呢存捺?我想最主要的表現(xiàn)就是 Obje...
    Ethan_Struggle閱讀 2,199評論 0 7
  • Method Swizzling 參考原文:http://nshipster.com/method-swizzli...
    Fsn_soul閱讀 312評論 0 0
  • 今天準(zhǔn)備學(xué)習(xí)Objective-C Runtime相關(guān)知識,看到了Method Swizzling技術(shù)曙蒸,并找到了介...
    koce_zhao閱讀 441評論 0 2
  • 繼上Runtime梳理(四) 通過前面的學(xué)習(xí)捌治,我們了解到Objective-C的動態(tài)特性:Objective-C不...
    小名一峰閱讀 758評論 0 3