iOS開發中亂用hook可能導致災難


今天有同事遇到問題,他重寫viewDidAppear:方法,但是,代碼並沒有執行到。后來我發現,是另個一同事用了黑魔法搞的鬼,而且他本人並不知道這么做會產生影響。(本文中所有黑魔法指Swizzle)

我展示下hook的代碼

[self aspect_hookSelector:@selector(viewDidAppear:) withOptions:AspectPositionBefore usingBlock:^(id<AspectInfo> info, BOOL animated) {

        UIViewController *vc = [info instance];

        [vc AspectBeforeViewDidAppear:animated];

    } error:&error];

 

    error = nil;

[self aspect_hookSelector:@selector(viewDidAppear:) withOptions:AspectPositionAfter usingBlock:^(id<AspectInfo> info, BOOL animated) {

         UIViewController *vc = [info instance];

        [vc AspectAfterViewDidAppear:animated];

    } error:&error];

作者的原意是想在viewDidAppear:執行過程中,在前面執行一些代碼,在后面也執行一些代碼。魔法的可怕之處來了:難以操控。

 

明白了需求,看看到底問題出在了哪里

 

先做如下指代原函數viewDidAppear:為SEL1,其實現IMP1

原函數執行后的函數SEL3——>IMP3(SEL3)

他設想的兩次hook方法實際執行如下。
第一次hook后,
原函數SEL1———>IMP2(SEL2)
原函數執行前的函數SEL2——>IMP1
原函數執行后的函數SEL3——>IMP3(SEL3),
第二次hook,
原函數SEL1———>IMP3(SEL3)
原函數執行前的函數SEL2——>IMP1
原函數執行后的函數SEL3——>IMP2(SEL2),
 
所以最后執行的順序是調用SEL1尋找到IMP3,執行IMP3的過程中,由於IMP3中會調用SEL3,也就是執行IMP2(如果不明白,請查看swizzle的實現)。原函數的理應被SEL3中調用指向IMP1(SEL2)調用到,但是aspects存在bug,導致IMP2中的SEL2丟失,導致原函數被跳過。aspects的相對而言調用了很多底層函數,合運行時,大部分開發者很難讀懂,除了問題也難也解決。
 
最后提出忠告,這種形式的AOP最好只處理簡單而統一的業務,這種情況下,的確可能讓代碼清晰,抽離不想干的邏輯。函數換來換去卻是挺繞的,除非你真的知道自己在做什么,否則還是換條路,不然也不好維護,同事可能會出現莫名其妙被捅了一刀的感覺。文筆不太好,再補充點,AOP很容易導致入侵性的代碼,最好不要去hook的方法里不要增加對系統sdk屬性的操作,你可以自己增加一些屬性來操作。以不影響別人的代碼

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM