Swift是否和OC一樣有runtime機制

來源:互聯網
上載者:User

標籤:

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機制

分析用例:



方法,屬性

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


調用showClsRuntime列印方法


列印如下:


 

對於純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,所以能被動態替換。

 

Swift是否和OC一樣有runtime機制

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.