Swift是否和OC同樣有runtime機制

Swift是否和OC同樣有runtime機制
函數

OC語言最大的特性無疑是其的動態性,能夠利用OC的動態性可以得到一個類的方法和屬性,從而實現靈活的程序,但Swift是否也包含了runtime機制呢?性能

參考連接:http://mp.weixin.qq.com /s?__biz=MzA3ODg4MDk0Ng==&mid=403153173&idx=1&sn=c631f95b28a0eb4b842a9494e43a30e5&scene=23&srcid=0331ZwO8t6uWiBON621r1GhC#rd測試

下面咱們將從純Swift的類和繼承OC的Swift類來闡述Swift的runtime機制優化

分析用例:spa



方法,屬性3d

動態性最重要的一點就是拿到某個類的方法和屬性,使用以下的方法打印類的方法和屬性繼承


調用showClsRuntime打印方法內存


打印以下:ci


 

對於純Swift的TestASwiftClass來講任何方法、屬性都未獲取到。文檔

對於TestSwiftClass來講除testReturnTuple、testReturnVoidWithaCharacter兩個方法外,其餘的都獲取成功了。

這是爲何呢?

1:純Swift類的函數調用已經不是OC那樣的運行時消息了,而是相似C++似得vtable,在編譯時就肯定了調用那個函數了.

2:而TestSwiftClass繼承自UIViewController也就是NSObject,Swift爲了兼容OC,因此繼承自NSObject的類都保留了他的動態性,因此咱們能經過runtime拿到他的屬性和方法.

但是爲何testReturnTuple、testReturnVoidWithaCharacter這兩個函數卻沒法經過runtime得到呢?

從OC的動態特性可知,全部運行時方法都依賴TypeEcoding,也就是method_getTypeEncoding函數,它指定了參數類型以及參數在入棧時的內存空間,沒有這個標識則無法入棧.而元祖,和字符類型是Swift獨有的,因此不能利用runtime得到他的方法.

方法替代

動態性最經常使用的方法就是方法替代,將某個類的方法替代爲自定義的方法,從而起到hook的做用.

 

  • 對於純Swift類(如TestASwiftClass)來講,沒法經過objc runtime替換方法,由於由上面的測試可知拿不到這些方法、屬性

  • 對於繼承自NSObject類(如TestSwiftVC)來講,沒法經過runtime獲取到的方法確定無法替換了。那能經過runtime獲取到的方法就都能被替換嗎?咱們測一把

    Method Swizzling的代碼以下


@objc

找到官方文檔讀讀。

能夠知道@objc是用來將Swift的API導出給Objective-C和Objective-C runtime使用的,若是你的類繼承自Objective-c的類(如NSObject)將會自動被編譯器插入@objc標識。

咱們在把TestASwiftClass(純Swift類)的方法、屬性前都加個@objc 試試,如圖: 

dynamic

文檔裏還有一句說明: 
加了@objc標識的方法、屬性沒法保證都會被運行時調用,由於Swift會作靜態優化。要想徹底被動態調用,必須使用dynamic修飾。使用dynamic修飾將會隱式的加上@objc標識。
這也就解釋了爲何testReturnVoidWithaId沒法被替換,由於寫在Swift裏的代碼直接被編譯優化成靜態調用了。

而viewDidAppear是繼承Objective-C類得到的方法,自己就被修飾爲dynamic,因此能被動態替換。

相關文章
相關標籤/搜索