由category為什麼不能新增屬性所想到的
在category裡新增屬性的情況?
在類中使用@property,系統會自動生成帶“_”的成員變數和該變數的setter和getter方法。也就是說,屬性相當於一個成員變數加getter和setter方法
在分類裡使用@property宣告屬性,只是將該屬性新增到該類的屬性列表,但是沒有生成相應的成員變數,也沒有實現setter和getter方法。
這篇博文將的很詳細 :
點我
不足之處還是沒有講出類別不能新增屬性的根本原因。
那麼根本原因又是什麼呢?
category 它是在執行期決議的。 因為在執行期即編譯完成後,物件的記憶體佈局已經確定,如果新增例項變數就會破壞類的內部佈局,這對編譯型語言來說是災難性的。
為什麼使用Runtime又可以新增屬性?
使用Runtime技術中的關聯物件可以為類別新增屬性。
其原因是:關聯物件都由AssociationsManager管理,AssociationsManager裡面是由一個靜態AssociationsHashMap來儲存所有的關聯物件的。這相當於把所有物件的關聯物件都存在一個全域性map裡面。而map的的key是這個物件的指標地址(任意兩個不同物件的指標地址一定是不同的),而這個map的value又是另外一個AssociationsHashMap,裡面儲存了關聯物件的kv對。
如合清理關聯物件?
runtime的銷燬物件函式objc_destructInstance裡面會判斷這個物件有沒有關聯物件,如果有,會呼叫_object_remove_assocations做關聯物件的清理工作。(詳見Runtime的原始碼)
這裡說一下category和extension的區別?
extension看起來很像一個匿名的category,但是extension和有名字的category幾乎完全是兩個東西。 extension在編譯期決議,它就是類的一部分,在編譯期和標頭檔案裡的@interface以及實現檔案裡的@implement一起形成一個完整的類,它伴隨類的產生而產生,亦隨之一起消亡。extension一般用來隱藏類的私有資訊,你必須有一個類的原始碼才能為一個類新增extension,所以你無法為系統的類比如NSString新增extension。(詳見2)
但是category則完全不一樣,它是在執行期決議的。
就category和extension的區別來看,我們可以推匯出一個明顯的事實,extension可以新增例項變數,而category是無法新增例項變數的(因為在執行期,物件的記憶體佈局已經確定,如果新增例項變數就會破壞類的內部佈局,這對編譯型語言來說是災難性的)。
參考博文:美團點評技術團隊 這篇文章非常好,建議大家都看一下。