如何為一個實例動態(tài)替換方法

作者Joy___已關注

2017.03.20 15:48*字數(shù) 583閱讀 78評論 4喜歡 5

這個 Tip 來源于一道面試題,感覺很是考察知識變通的能力,對 KVO 深入了解的同學聘惦,應該很容易就可以答出來。這里拋磚引玉示损,簡單聊聊這個 Tip

首先簡單總結下 KVO 的大概原理

當你觀察一個對象時朗和,會動態(tài)的創(chuàng)建該對象類的子類,這個子類重寫了被觀察屬性的 setter 方法谊娇,同時將該對象的 isa 指針指向了新創(chuàng)建的子類肺孤。在 Objective-C 中對象是通過 isa 指針來查找對應類中的方法列表的,所以這里可以把該對象看為新子類的實例對象济欢。重寫的 setter 方法會在調(diào)用原 setter 方法之后赠堵,通知觀察者對象屬性值的更改。

好的法褥,下面進入正題茫叭,聊聊如何為一個實例動態(tài)替換方法。

首先創(chuàng)建一個初始化工程半等,直接對 ViewController 進行實戰(zhàn)即可杂靶,在 ViewController 中加入一個 eat 方法,如下

- (void)viewDidLoad {? ? [superviewDidLoad];self.view.backgroundColor = [UIColorredColor];}- (void)eat {NSLog(@"original eat");}

然后寫一個 NSObject 的 Category 負責進行方法交換酱鸭,將原對象的 isa 指針指向該對象類的子類(LDSubclass)吗垮,并在子類中重寫 eat 方法

@implementationNSObject (Hook)+ (void)hookWithInstance:(id)instancemethod:(SEL)selector{

Method originMethod = class_getInstanceMethod([instance class], selector);

if (!originMethod) {

// exception ..

}ClassnewClass = [LDSubclassclass];// 修改 isa 指針的指向object_setClass(instance, newClass);}@end

子類的代碼很簡單,就是重寫 eat 方法凹髓,如果有需要烁登,可以調(diào)用原方法的實現(xiàn)

@implementationLDSubclass- (void)eat {? ? NSLog(@"newSubClass eat");? ? struct objc_supersuperClazz = {? ? ? ? .receiver = self,? ? ? ? .super_class=class_getSuperclass(object_getClass(self))? ? };// 調(diào)用原方法void(*objc_msgSendSuperCasted)(void*, SEL) = (void*)objc_msgSendSuper;? ? objc_msgSendSuperCasted(&superClazz,_cmd);}@end

最后在 ViewControlller 中進行測試即可,此時的 ViewController 代碼如下

@implementationViewController- (void)viewDidLoad {? ? [superviewDidLoad];self.view.backgroundColor = [UIColorredColor];? ? ViewController * vc = [[ViewController alloc] init];? ? [vc eat];NSLog(@"-----------");? ? ViewController * hookedInstance= [[ViewController alloc] init];? ? [ViewController hookWithInstance:hookedInstance method:@selector(eat)];? ? [hookedInstance eat];}- (void)eat {NSLog(@"original eat");}@end

來看看打印的結果蔚舀,第一個沒有 Hook 的實例饵沧,正常執(zhí)行;第二個Hook 后的實例赌躺,先執(zhí)行重寫的方法狼牺,后執(zhí)行原方法。

2017-03-2014:30:21.244JYHookInstanceMethod[91153:3422584]originaleat2017-03-2014:30:21.244JYHookInstanceMethod[91153:3422584]-----------2017-03-2014:30:21.245JYHookInstanceMethod[91153:3422584]newSubClasseat2017-03-2014:30:21.245JYHookInstanceMethod[91153:3422584]originaleat

原理

與 KVO 的 isa-swizzling 思路相同礼患,對想要 Hook 實例的類創(chuàng)建一個子類是钥,并在子類中重寫想要 Hook 的方法掠归,將該實例的 isa 指針指向子類,這樣進行方法查找時悄泥,便會在子類方法列表進行查找虏冻,如果想要執(zhí)行更多操作,可以在替換后的新方法中加入自己的邏輯弹囚。

這里只是一個超級簡單的 Demo厨相,很多邊界情況沒有考慮,后期可以自己完善鸥鹉,Demo 可以參考JYHookInstanceMethod

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蛮穿,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子毁渗,更是在濱河造成了極大的恐慌绪撵,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件祝蝠,死亡現(xiàn)場離奇詭異,居然都是意外死亡幻碱,警方通過查閱死者的電腦和手機绎狭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來褥傍,“玉大人儡嘶,你說我怎么就攤上這事』蟹纾” “怎么了蹦狂?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長朋贬。 經(jīng)常有香客問我凯楔,道長,這世上最難降的妖魔是什么锦募? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任摆屯,我火速辦了婚禮,結果婚禮上糠亩,老公的妹妹穿的比我還像新娘虐骑。我一直安慰自己,他們只是感情好赎线,可當我...
    茶點故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布廷没。 她就那樣靜靜地躺著,像睡著了一般垂寥。 火紅的嫁衣襯著肌膚如雪颠黎。 梳的紋絲不亂的頭發(fā)上另锋,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天,我揣著相機與錄音盏缤,去河邊找鬼砰蠢。 笑死,一個胖子當著我的面吹牛唉铜,可吹牛的內(nèi)容都是我干的台舱。 我是一名探鬼主播,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼潭流,長吁一口氣:“原來是場噩夢啊……” “哼竞惋!你這毒婦竟也來了?” 一聲冷哼從身側響起灰嫉,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤拆宛,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后讼撒,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體浑厚,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年根盒,在試婚紗的時候發(fā)現(xiàn)自己被綠了钳幅。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,133評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡炎滞,死狀恐怖敢艰,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情册赛,我是刑警寧澤钠导,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站森瘪,受9級特大地震影響牡属,放射性物質發(fā)生泄漏。R本人自食惡果不足惜扼睬,卻給世界環(huán)境...
    茶點故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一湃望、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧痰驱,春花似錦证芭、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蝇完,卻和暖如春官硝,著一層夾襖步出監(jiān)牢的瞬間矗蕊,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工氢架, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留傻咖,地道東北人。 一個月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓岖研,卻偏偏與公主長得像卿操,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子孙援,可洞房花燭夜當晚...
    茶點故事閱讀 45,077評論 2 355

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

  • 這個 Tip 來源于一道面試題害淤,感覺很是考察知識變通的能力,對 KVO 深入了解的同學拓售,應該很容易就可以答出來窥摄。這...
    Joy___閱讀 2,863評論 6 33
  • 轉至元數(shù)據(jù)結尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,721評論 0 9
  • *面試心聲:其實這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個offer,總結起來就是把...
    Dove_iOS閱讀 27,151評論 30 470
  • 一础淤、深復制和淺復制的區(qū)別崭放? 1、淺復制:只是復制了指向對象的指針鸽凶,即兩個指針指向同一塊內(nèi)存單元币砂!而不復制指向對象的...
    iOS_Alex閱讀 1,378評論 1 27
  • 昨天晚上兒子打電話回來,聲音聽起來已經(jīng)不是原來那么稚嫩了吱瘩,問他這學期感覺怎么樣?他說很好迹缀,說自己感冒了使碾,老師有幫他...
    心若止水858閱讀 226評論 0 0