原來這纔是`Method-Swizzling`正確姿式

前言

昨天在翻閱DZNEmptyDataSet源碼時發現了一些有趣的東西,如今和你們分享下:objective-c

  • Method-Swizzling不是在+load方法中
  • Method-Swizzling的方式並無使用method_exchangeImplementations()函數

下面一塊兒來探索一番吧!函數

按需交換方法

這點比較好理解,直到須要的時候纔去Swizzling,而不是在+load方法中。關於在+load方法中進行Method-Swizzling,這裏有篇文章參考。下面是相關方法的截圖。具體代碼你們能夠去GitHub圍觀。 spa

"很是規"的Swizzling

這點須要細說下。平時你們對於Method-Swizzling的印象大多停留在+load的階段,忽然間,這個源碼裏找不到+load的影子,感受少了點啥。還好DZNEmptyDataSet留下了參考,讓咱們一探究竟。3d

下面的觀點來源於這裏,你們能夠自行參考code

從發送消息提及

假設如今有以下類實現: cdn

在咱們本身的實現方法swizzle_originalMethod中,經過[self swizzle_originalMethod];調用了原有的方法實現,這是你們一般的作法。blog

換成發送消息的寫法就是:get

((void(*)(id, SEL))objc_msgSend)(self, @selector(swizzle_originalMethod));
複製代碼

再看下沒有Method-Swizzling以前,對原有實現的調用時什麼樣的:源碼

((void(*)(id, SEL))objc_msgSend)(self, @selector(originalMethod));
複製代碼

二者對比,很明顯,咱們改變了發送消息時的第二個參數 - 方法選擇子,也就是說這種Method-Swizzling技術留有「罪證」。若是原有方法實現依賴了這個方法選擇子,它將沒法正常工做。it

解決方案 - 使用method_setImplementation

直接給出代碼:

咱們使用了method_setImplementation方法替換以前的實現,並使用靜態變量保存了原有實現。這樣就不會以前的問題了。達到了無痕的目的。

固然,這裏的method_setImplementation也須要控制其執行的次數的!!!

結語

多翻看大神們的源碼,仍是有好處的。😂😂😂

  • 若有錯誤,還請指出。共勉!
  • 您的喜歡是最大的讚揚。
相關文章
相關標籤/搜索