淺談Categroy不能為原類新增Property的原因

weixin_33830216發表於2017-02-22
在日常的開發當中我們經常使用Category來處理一些問題,但是Category有個蛋疼的事,不能為原類新增屬性。瞭解過Runtime的小夥伴都知道,我們可以利用runtime來解決這個問題。但是今天我們來了解一下Category為什麼不能為原類新增屬性。

我們先來建立一個Book類,定義一個屬性BookName。

@interface Book : NSObject

@property (nonatomic, copy) NSString *bookName;

@end

再來建立一個分類,定義一個屬性。

@interface Book (Property)

@property (nonatomic, copy) NSString *author;

@end

這裡大家要先了解一下屬性的構成

Property(屬性) = ivar(例項變數) + setter + getter

接下來我們可以利用runtime來列印一下。

//獲取類的成員變數
- (void)getClassIvars {
    
    unsigned int count;
    
    //獲取成員變數的陣列的指標
    Ivar *ivars = class_copyIvarList([Book class], &count);
    
    for (int i = 0; i < count; i++) {
        Ivar ivar = ivars[i];
        
        //根據ivar獲得其成員變數的名稱
        const char *name = ivar_getName(ivar);
        //c的字串轉oc的字串
        NSString *key = [NSString stringWithUTF8String:name];
        NSLog(@"ivar__%d == %@",i,key);
    }
    //記得釋放
    free(ivars);
    //如果你的成員私有,也可以獲取到 比如_education
}
//獲取類的成員屬性
- (void)getClassProperty {
    unsigned int count;
    
    //獲得指向該類所有屬性的指標
    objc_property_t *properties = class_copyPropertyList([Book class], &count);
    
    for (int i = 0; i < count; i++) {
        //獲取該類的一個屬性的指標
        objc_property_t property = properties[i];
        //獲取屬性的名稱
        const char *name = property_getName(property);
        //將c的字串轉化為OC字串
        NSString *key = [NSString stringWithUTF8String:name];
        
        NSLog(@"propertyLabel__%d == %@",i,key);
    }
    //記得釋放
    free(properties);
    
}

列印結果

2017-02-22 14:57:21.218 DDTool[1757:134117] ivar__0 == _bookName
2017-02-22 14:57:21.219 DDTool[1757:134117] property__0 == author
2017-02-22 14:57:21.219 DDTool[1757:134117] property__1 == bookName
2017-02-22 14:57:21.219 DDTool[1757:134117] method__0 == bookName 2
2017-02-22 14:57:21.219 DDTool[1757:134117] method__1 == setBookName: 3
2017-02-22 14:57:21.219 DDTool[1757:134117] method__2 == .cxx_destruct 2
  • 這裡我們可能有一個疑惑,pro_list列印的結果中不是有author這個屬性麼(這個下面會說,我們先觀察重點),我們發現ivar_list列印的結果中只有_bookName這個例項變數,沒有_author。這樣我們就可以大概知道為什麼新增不了屬性了,沒有滿足屬性的構成條件。
  • 接著上面的疑問來講,其實這裡列印的pro_list並非是上文所述的屬性,它只是一個屬性的描述。這裡看到其他的部落格上有講到:

每次在增加一個屬性,系統都會在ivar_list中新增一個成員變數的描述,在method_list中增加setter與getter方法的描述,在pro_list中增加一個屬性的描述,然後計算該屬性在物件中的偏移量,然後給出setter與getter方法對應的實現。

至於Category為什麼沒有生成ivar,是因為分類本身並不是一個真正的類,它並沒有自己的isa。

以上是自己在查閱資料後的一些淺層理解,不正確的、不足的地方還有望指出。?

相關文章