在OC中:
API: class_addMethod往一個Class里添加method
API: class_getInstanceMethod或class_getClassMethod可以判斷某個SEL是否存在于Class
API: method_exchangeImplementations 交換方法。
最近工作上做了一件事,簡單點說就是需要把一些特定Class里的方法func,替換成Hook_func,當Hook_func執(zhí)行完之后,再執(zhí)行func。于是很簡單地想到了往Class添加一個Hook_func,然后再交換func與Hook_func,就能到達目的。
但是,在實現(xiàn)后,卻出現(xiàn)了死循環(huán),糾其原因,因為部分Class間存在著繼承關(guān)系,沒有正確地將Method添加到正確的Class中導致。
當時為了解決這個問題,重新去理清楚了一下Class中 SEL 與 Method的關(guān)系。SEL是一個選擇器,相當于指向一個Method的指針,將SEL指向不同的Method,它就會有不一樣的特性,method_exchangeImplementations也就是交換SEL指向的Method值來實現(xiàn)方法交換的。
在調(diào)用class_getInstanceMethod時,是會檢查superClass的。
如下圖,當ClassB繼承ClassA時, ClassB中沒有SEL func,而ClassA中有SEL func。
這時調(diào)用class_getInstanceMethod(ClassB, @selector(func)),是能拿到SEL func的Method的,然后再將ClassB中添加SEL Hook_func后,變成下圖。
對ClassB調(diào)用method_exchangeImplementations后,得到下圖。
這里可以看到,其實ClassA中的SEL:func已經(jīng)是指向Method:Hook_func。在對ClassB的實例調(diào)用SEL:func時,能達到之前預訂的效果,即先執(zhí)行Hook_func后再執(zhí)行func。
但在這個時候,如果再對ClassA做類似ClassB的處理,將得到下圖:
這時SEL:func和SEL:Hook_func都指向了Method:Hook_func,于是便出現(xiàn)了死循環(huán)的問題。
最終的解決方法從上圖已經(jīng)可以很明顯的看出來了,即在對ClassB做處理的時候,添加的SEL:Hook_func不應該添加到ClassB上,而應該添加到ClassA上,如下圖,則問題得已解決。
執(zhí)行下面的這個函數(shù),找到正確的Class,然后再往Class里添加方法和交換方法,問題就解決了:
延伸閱讀
- ssh框架 2016-09-30
- 阿里移動安全 [無線安全]玩轉(zhuǎn)無線電——不安全的藍牙鎖 2017-07-26
- 消息隊列NetMQ 原理分析4-Socket、Session、Option和Pipe 2024-03-26
- Selective Search for Object Recognition 論文筆記【圖片目標分割】 2017-07-26
- 詞向量-LRWE模型-更好地識別反義詞同義詞 2017-07-26
- 從棧不平衡問題 理解 calling convention 2017-07-26
- php imagemagick 處理 圖片剪切、壓縮、合并、插入文本、背景色透明 2017-07-26
- Swift實現(xiàn)JSON轉(zhuǎn)Model - HandyJSON使用講解 2017-07-26
- 阿里移動安全 Android端惡意鎖屏勒索應用分析 2017-07-26
- 集合結(jié)合數(shù)據(jù)結(jié)構(gòu)來看看(二) 2017-07-26