在objc2之后class的結(jié)構(gòu)是這樣的
struct objc_class : objc_object {
? ? // Class ISA;? ? Class superclass;
? ? cache_t cache;? ? ? ? ? ? // formerly cache pointer and vtable?
class_data_bits_t bits;? ? // class_rw_t * plus custom rr/alloc flags
}
這里的bits是個共用體union
bits & mask之后獲得一個結(jié)構(gòu)體 class_rw_t:
struct class_rw_t {
? ? uint32_t flags;
? ? uint32_t version;
? ? const class_ro_t *ro;
? ? method_array_t methods;
? ? property_array_t properties;
? ? protocol_array_t protocols;
? ? Class firstSubclass;
? ? Class nextSiblingClass;
? ? char *demangledName;
}
const class_ro_t *ro
struct class_ro_t {
? ? uint32_t flags;
? ? uint32_t instanceStart;
? ? uint32_t instanceSize;#ifdef __LP64__? ? uint32_t reserved;#endif? ? const uint8_t * ivarLayout;
? ? const char * name;
? ? method_list_t * baseMethodList;
? ? protocol_list_t * baseProtocols;
? ? const ivar_list_t * ivars;
? ? const uint8_t * weakIvarLayout;
? ? property_list_t *baseProperties;
? ? method_list_t *baseMethods() const {
? ? ? ? return baseMethodList;
? ? }
};
class_rw_t顧名思義,擁有讀寫權(quán)限潦牛,ro就是只讀的意思袭景,ivars放在class_ro_t里面,所以ivar在編譯時期已經(jīng)是固定的了号杠,之后不能動態(tài)的添加更改蚪腋,但是property,和methods在rw_t里面姨蟋,所以可以允許動態(tài)添加屉凯。
還要就是instanceSize也是放在class_ro_t里的,所以類的大小是在編譯時期已經(jīng)決定的了眼溶∮蒲猓可以這么理解,ivars放在class_rw_t堂飞,那有可能以后獲得size就錯誤灌旧。
二:那為啥會是這樣的設(shè)計呢?
其實也不難绰筛。成員變量枢泰,屬性其實都是屬于它的實例的,不同的實例铝噩,他們的成員變量都是不同的衡蚂,所以他們都存儲在所在實例的堆空間中,互不干擾骏庸,而且加入程序運行后再動態(tài)添加屬性毛甲,那該類原來的子類的空間布局是不是也要相應(yīng)的做出改變呢?敞恋。但是方法確實公用的丽啡,不同的實例所調(diào)用的方法都是一樣的,而且我們也知道硬猫,方法其實是存在于代碼區(qū)的补箍,所以即使動態(tài)的添加方法改执,也不影響原來架構(gòu)和功能。