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;//协议列表
} 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对应的实现)
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:方法的集合,用于优化消息派发流程(下一篇文章会详细讲解),而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) 发送drink消息,运行时会通过isa指针查找到Person(Class),这里保存着本类中定义的实例方法的指针。
[Person drink2];
我们向Person(Class)发送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的位置。