在swift中探索runtime中的方法一

提起運(yùn)行時(shí),相信不少跟我一樣剛剛步入iOS開發(fā)沒(méi)多久的菜鳥對(duì)其都比較模糊,因此抽時(shí)間探索了一下runtime文件里面的方法,并親自測(cè)試其用法。但因?yàn)榉椒ㄌ?因此不能在一篇文章中講完,因此打算寫一個(gè)系列專題,每篇文章中講述的方法大約在五個(gè)左右。由于工作需要,平時(shí)用的是swift語(yǔ)言,因此示例程序都是用swift寫的。關(guān)于運(yùn)行時(shí)有哪些用法,網(wǎng)上有很多的文章都有詳細(xì)的描述,這里就不再贅言。

進(jìn)入runtime文件,最先看到的是四個(gè)自定義類型

public typealias Method = COpaquePointer//定義對(duì)象方法或者類方法
public typealias Ivar = COpaquePointer//定義對(duì)象的實(shí)例變量,包括類型和名字。
public typealias Category = COpaquePointer
public typealias objc_property_t = COpaquePointer//定義屬性

在swift中當(dāng)我們想自定義一種數(shù)據(jù)類型時(shí),可以使用typealias。在C和C++中有一種不透明的指針,顧名思義,就是無(wú)法拿到具體的定義,指向的是不確定類型。在swift中就用 COpaquePointer對(duì)應(yīng)這類不透明的指針,當(dāng)然對(duì)于那些能找到對(duì)應(yīng)類型表示指針指向的類型,可以使用UnsafePointer。

下面開始探索runtime文件中的方法,由于方法眾多,因此按照文件中方法的順序作一一講解。
1 該方法接收一個(gè)任意類型的對(duì)象,返回的是該對(duì)象的具體類型。

@available(iOS 2.0, *) //swift中AnyObject對(duì)應(yīng)OC中的id類型
public func object_getClass(obj: AnyObject!) -> AnyClass!

2 將一個(gè)對(duì)象設(shè)置為別的類類型,返回原來(lái)的Class。

@available(iOS 2.0, *)
public func object_setClass(obj: AnyObject!, _ cls: AnyClass!) -> AnyClass!

這里對(duì)該方法做了一個(gè)簡(jiǎn)單的測(cè)試,有兩個(gè)自定義類,一個(gè)MyText類,一個(gè)Dog類,測(cè)試代碼如下。

let objc = MyText()
print(object_getClass(objc)) 
object_setClass(objc, Dog().dynamicType)
print(object_getClass(objc))

輸出結(jié)果如下:

MyText
Dog          

經(jīng)過(guò)測(cè)試很明顯的發(fā)現(xiàn)objc的類型在調(diào)用過(guò)此方法后的類型變成了Dog類型。不過(guò)在做這個(gè)方法的測(cè)試時(shí)發(fā)現(xiàn)兩個(gè)問(wèn)題,一是該方法的第二個(gè)參數(shù)用
dynamicType獲取對(duì)象類時(shí)不能用系統(tǒng)的類,只能用自定義的類。當(dāng)然如果我們?cè)谄胀ùa中這樣寫是不會(huì)有問(wèn)題的。另外一個(gè)問(wèn)題是,經(jīng)過(guò)這個(gè)方法后我們的objc對(duì)象類型已經(jīng)是Dog,但是我們卻無(wú)法訪問(wèn)Dog類中的屬性,卻能夠訪問(wèn)MyText類中的方法,這里作者猜測(cè)可能與OC是動(dòng)態(tài)運(yùn)行時(shí)的語(yǔ)言,swift是靜態(tài)的語(yǔ)言,在編譯階段對(duì)象的屬性就已經(jīng)確定有關(guān)。

3 該方式是判斷傳入的對(duì)象是否是類對(duì)象。//類也是對(duì)象,稱為類對(duì)象,是元類類型的對(duì)象。關(guān)于元類后期會(huì)專門寫一篇文章講述。

@available(iOS 8.0, *)
public func object_isClass(obj: AnyObject!) -> Bool

測(cè)試代碼和運(yùn)行結(jié)果如下:

print(object_isClass(Dog()))
print(object_isClass(Dog().dynamicType))

false
true

4 獲取對(duì)象的類名。

@available(iOS 2.0, *)
public func object_getClassName(obj: AnyObject!) -> UnsafePointer<Int8>

5 獲取對(duì)象某一實(shí)例變量的值。

@available(iOS 2.0, *)
public func object_getIvar(obj: AnyObject!, _ ivar: Ivar) -> AnyObject!

測(cè)試代碼如下:

let objc = MyText()
let ivar = class_getInstanceVariable(objc.dynamicType, "textString")
print(object_getIvar(objc, ivar))

這個(gè)方法要與class_getInstanceVariable配合使用才能獲取到對(duì)象的實(shí)例變量的值。class_getInstanceVariable該方法有兩個(gè)參數(shù),第一個(gè)是對(duì)象的類,第二個(gè)參數(shù)是屬性名。在做這個(gè)方法的測(cè)試時(shí)作者遇到一個(gè)問(wèn)題,那就是textString屬性的類型為基本數(shù)據(jù)類型或者是swift中的對(duì)象類型(例如String)時(shí)就會(huì)崩潰。只有是OC中的對(duì)象時(shí)才能正常獲取,這里沒(méi)有再深入的研究,因此對(duì)于出現(xiàn)崩潰的原因也不是很明確。

由于用swift測(cè)試runtime方法時(shí)容易出現(xiàn)問(wèn)題,在下一篇文章中將暫時(shí)使用OC去做測(cè)試,可能是swift與OC環(huán)境的差異所致。由于筆者參加工作沒(méi)多久,能力尚且不足,在文中可能出現(xiàn)的錯(cuò)誤還希望各位讀者發(fā)現(xiàn)后能夠及時(shí)指出,學(xué)海無(wú)涯,共同進(jìn)步。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容