天天看點

Swift 4.2 動态擷取一個類的屬性,方法,和變量。前言實驗結論:

前言

對于OC來說可以動态擷取類的屬性、方法等資訊,但是對于Swift來說能不能擷取到呢,我們先來看個實驗。

實驗

首先定義個純Swift類,沒有繼承NSObject。

class PersonModel {
    var name = "張三";
    var age = 18;
    
    func printInfo() -> Void {
        print("姓名:\(name)\n年齡:\(age)");
    }
}
           

上邊定義了簡單的PersonModel類,沒有繼承任何類,那麼我們通過runtime看看是否可以擷取這個類的屬性麼。

測試案例:

let model = PersonModel();
    var count: UInt32 = 0;
    let cls = object_getClass(model);

    let plist = class_copyPropertyList(cls, &count);

    print("===開始擷取");
    for item in 0..<count {
        let property = plist?[Int(item)]
        let cname = property_getName(property!);
        let name = String(cString: cname);
        
        print("property:<\(name)>")
    }
    print("===結束擷取");
           

下圖是輸出結果:

Swift 4.2 動态擷取一個類的屬性,方法,和變量。前言實驗結論:

可以看到沒有擷取到任何屬性。

那麼我們就可以得出結論,純Swift在runtime是沒有辦法擷取類的屬性的。那麼擷取類的方法呢,我們再看下面的測試。

代碼接着測試:

print("===開始擷取");
    let methodList = class_copyMethodList(cls, &count);
    for item in 0..<count {
        let meth = methodList![Int(item)];
        let m = method_getName(meth);
        let mStrl = NSStringFromSelector(m);
        print("方法:\(mStrl)");
    }
    print("===結束擷取");
           
Swift 4.2 動态擷取一個類的屬性,方法,和變量。前言實驗結論:

同樣沒有擷取任何函數, 純swift在runtime運作的時候是沒有辦法擷取函數的。

由此可以推論出,純swift在runtime運作的時候是沒有辦法擷取到類任何資訊。也可以看出swift并不支援動态擷取資訊。

那麼我們就真的沒有辦法擷取類的屬性了麼?我們知道swift是可以和OC混合開發的,也就是swift也支援OC,但是OC确實動态語言,是以swift也會不會繼承OC的特性呢。我們趕緊測試一下。

我們先改一下這個PersonModel類。讓他繼承NSObject類。如下:

class PersonModel : NSObject{
    var name = "張三";
    var age = 18;
    
    func printInfo() -> Void {
        print("姓名:\(name)\n年齡:\(age)");
    }
}
           

我們在運作一邊上邊的測試案例;會發現一個并沒有擷取到自己定義的任何資訊,現在是用swift 4.2版本測試的,這個因為swift 4.2版本已經把@objc 去掉了,繼承NSObject的類不會再自動生成@objc 的特性了,需要我們手動添加,這個@objc 是幹什麼的呢,添加這個是表明改屬性具有OC屬性的特性。那麼我們加上以後,會看到如下的輸出:

Swift 4.2 動态擷取一個類的屬性,方法,和變量。前言實驗結論:

 這個輸出結果看着是不是很像OC的方法。對,就是,加了@objc 就會預設生成OC的get、set方法。還有兩個函數init、.cxx_destruct這兩個函數,以後再說。先不用管。

通過以上測試我們可以看到,繼承NSObject添加的@objc 我們才可以擷取到類的屬性和方法。

結論:

純Swift是在編譯的時候已經确定了要調用的方法,而不是在運作的時候确定,這個和C有點類似,是以我們是沒有辦法在運作時擷取方法和屬性的。

對于繼承OC的swift,并且有@objc 特性,才會保留OC運作時的特性。我們才可以在運作時候擷取他們的屬性和方法。

繼續閱讀