如何判斷method是否被swizzling

2021-09-19 14:57:44 字數 1833 閱讀 8698

objective-c的動態性可以讓我們幹很多事情。比如method swizzling.

method swizzling有很多負面影響,特別是引入第三方元件後. 如果希望在執行時檢測,method是否被swizzling呢?

最近在翻看clang文件時發現可以使用這樣一種方法:

static inline bool isdiff(const char *func, sel _cmd)

; if (strlen(func) > 2)

return false;

}#define alert_if_method_replaced assert(!isdiff(__pretty_function__, _cmd));

__pretty_function__是乙個編譯器的巨集,在編譯期就由編譯器決定了,以-[myobject dosth]為例,在該方法內__pretty_function__為"-[myobject dosth]".而_cmd是方法的隱藏引數,是動態的,同樣以-[myobject dosth]為例,_cmd為"dosth",如果我們執行了一下**:

method ori_method = class_getinstancemethod([myobject class], @selector(dosth));

method replace_method = class_getinstancemethod([myobject class], @selector(dosth2));

method_exchangeimplementations(ori_method, replace_method);

那麼在原來的-[myobject dosth]函式體中,_cmd為"dosth2",而__pretty_function__保持不變。

利用上述特性,前文提到的巨集就可以工作了。如下述**:

method ori_method = class_getinstancemethod([myobject class], @selector(dosth));

method replace_method = class_getinstancemethod([myobject class], @selector(dosth2));

method_exchangeimplementations(ori_method, replace_method);

- (void) dosth

- (void) dosth2

然而一般情況下此方法,並沒有什麼卵用╮(╯_╰)╭ 

因為但凡重要的方法,一般是系統方法,如-[uiviewcontroller viewdidload],因為無法在該函式體使用上述巨集,所以無法檢測是否有swizzle。此外如果在dosth2中並沒有呼叫dosth2,那麼也沒有效果。

這裡有一篇講如何獲取當前method的imp,戳這裡.試了一下,年代比較久遠。可用性已經不太好了。╮(╯_╰)╭ 

不過。在作者的實現使用了__builtin_return_address(0),獲取當前棧的返回位址。這是值得習得的小技能。

後面會繼續找一些優雅的檢測系統方法被method swizzling的情形。imp相關的東西比較有意思。持續發現中。

原作寫於segmentfault 鏈結

如何判斷新網域名稱是否被K過

如何判斷新網域名稱是否被k過 大家在製作完乙個 以後,都要給這個 選個網域名稱,而網域名稱的選擇在優化中也是很重要的一步,選擇乙個好的網域名稱,對 的發展會有很大的幫助,如果選擇了乙個被k過或者作弊過的網域名稱,那麼對於 的流量特別是在搜尋引擎中的表現,那就有很大的影響了,那麼如何才能判斷乙個網域名...

判斷檔案是否被開啟

判斷檔案是否被開啟 方法一 通過try catch對檔案的移動操作,如果檔案開啟,將不能移動,會進入catch段 通過返回bool值來反應是否能正常移動 private void button2 click object sender,eventargs e private static bool ...

如何判斷乙個檔案是否被關閉?

做專案的時候遇到了下面這個問題 如何判斷乙個開啟的txt檔案是否被關閉?在開啟乙個txt檔案的時候,notepad程式是自動通過檔案路徑的引數首先複製檔案,然後馬上就關閉了檔案通道,這個時候開啟的其實只是notepad程式而不是檔案本身。檔案本身的開啟與關閉是一瞬間的事情。也就是說notepad程式...