iOS中的類和對象
1.runtime里面聲明了id和Class码耐,簡化得到以下
struct objc_class {
struct objc_class *isa;
}
struct objc_object {
struct objc_class *isa;
}
typedef struct objc_class *Class;//類(class object)
typedef struct objc_object *id;//對象(instance of class)
可以看到iOS中id代表了一個對象畴嘶,凡是首地址是*isa的指針,都可以看成對象凝垛,像前一篇文章的說的
Block原理解析懊悯。可以通過查看isa指針梦皮,查找到對象所屬的類別
我們看看objc_class是什么東西炭分。通過查看源碼,可以得到
struct objc_class {
Class isa OBJC_ISA_AVAILABILITY;
Class super_class OBJC2_UNAVAILABLE;//父類
const char *name OBJC2_UNAVAILABLE;//類名
long version OBJC2_UNAVAILABLE;
long info OBJC2_UNAVAILABLE;
long instance_size OBJC2_UNAVAILABLE;
struct objc_ivar_list *ivars OBJC2_UNAVAILABLE;//ivar列表(ivar:對象的實例變量剑肯,包括類型和名字)
struct objc_method_list **methodLists OBJC2_UNAVAILABLE;//方法列表
struct objc_cache *cache OBJC2_UNAVAILABLE;//方法緩存列表
struct objc_protocol_list *protocols OBJC2_UNAVAILABLE;//協(xié)議列表
} OBJC2_UNAVAILABLE;
我將里面的重點幾個struct拉出來講講
1.objc_ivar_list //ivar的列表捧毛,一個ivar定義對象的實例變量,包括類型和名字
struct objc_ivar {
char *ivar_name OBJC2_UNAVAILABLE;
char *ivar_type OBJC2_UNAVAILABLE;
int ivar_offset OBJC2_UNAVAILABLE;
int space OBJC2_UNAVAILABLE;
} OBJC2_UNAVAILABLE;
struct objc_ivar_list {
int ivar_count OBJC2_UNAVAILABLE;
int space OBJC2_UNAVAILABLE;
/* variable length structure */
struct objc_ivar ivar_list[1] OBJC2_UNAVAILABLE;
}
2.objc_method_list //方法列表,objc_method_list 存儲了objc_method让网,一個objc_method包含了SEL(可以理解成方法名的映射)和IMP(方法名SEL對應的實現(xiàn))
struct objc_method {
SEL method_name OBJC2_UNAVAILABLE;
char *method_types OBJC2_UNAVAILABLE;
IMP method_imp OBJC2_UNAVAILABLE;
} OBJC2_UNAVAILABLE;
struct objc_method_list {
struct objc_method_list *obsolete OBJC2_UNAVAILABLE;
int method_count OBJC2_UNAVAILABLE;
int space OBJC2_UNAVAILABLE;
/* variable length structure */
struct objc_method method_list[1] OBJC2_UNAVAILABLE;
}
3.objc_cache:方法的集合呀忧,用于優(yōu)化消息派發(fā)流程(下一篇文章會詳細講解),而Method和objc_method指的是同一個struct溃睹,只是通過typedef進行了重命名
struct objc_cache {
unsigned int mask /* total = mask + 1 */ OBJC2_UNAVAILABLE;
unsigned int occupied OBJC2_UNAVAILABLE;
Method buckets[1] OBJC2_UNAVAILABLE;
};
所有對象的實例變量的isa都指向Class而账,而Class的isa指針都指向meta-Class。
方法調用:
如有一個Person類因篇,它的實例變量jimmy的isa指針指向Person(Class)泞辐,而Person(Class)的isa指針指向Person(meta-Class)。
Person(Class)是一個全局變量竞滓,其中記錄了類名铛碑,成員變量信息,property信息虽界,protocol信息汽烦,實例方法列表等。
Person(meta-Class)是一個全局變量莉御,其中記錄了類名撇吞,類方法列表等俗冻。
Person *jimmy = [Person new];
[jimmy drink];
我們向jimmy(instance) 發(fā)送drink消息,運行時會通過isa指針查找到Person(Class),這里保存著本類中定義的實例方法的指針牍颈。
[Person drink2];
我們向Person(Class)發(fā)送drink2消息迄薄,運行時會通過isa指針查找到Person(meta-Class),這里保存著本類中定義的類方法的指針。
繼承體系中isa和superClass指針的走向:
objc_class中除了isa指針外煮岁,還有個super_class指針讥蔽,明顯super_class指的是父類。而如果有NyanCat:Cat:NSObject 這樣一個繼承樹画机,畫出圖來就是這樣冶伞。
如圖所示,跟隨黑線步氏,可以看到isa的指向响禽。運行時,每個對象的isa都不為空荚醒,這樣只要是一個id類型對象芋类,runtime都可以通過訪問首地址偏移(isa)來獲取該對象的信息。
上圖中跟隨綠線界阁,可以看到superclass的指向侯繁。當運行時在搜尋方法、ivar信息時泡躯,如果沒有找到信息巫击,則會沿superclass的線查找上去,最終NSObject(根類)的superclass是nil精续。
如果自己定義了一個根類(比如NSProxy)坝锰,則這個根類會替換圖中NSObject的位置。