1:结构
1:NSObject在内存中的大小:
系统分配给NSObject实例对象16个字节,但是对象只用了8个字节.
2:OC 对象分三类:实例对象(instance)、类对象(Class)、元类对象(MetaClass).
instance:存放了isa、成员变量值。
Class:isa,superCalss,cache_t, class_data_bits_t四个成员。
MetaClass: 结构和类对象一致,只是它存的数据比类对象少,存了类对象方法,isa,superClass。其他很多地方都是nil。
2 成员具体内容
1 class_data_bits_t
class_data_bits_t&FAST_DATA_MASK获取的class_rw_t 中存了成员方法列表,属性列表,协议列表,flags,version等一些信息。这三个列表是二维数组(数组的成员是每个类的所有分类的一位数组方法列表,属性列表,协议列表)。
class_ro_t 中也存了方法列表,协议列表, 属性列表。但是这个结构体里的列表都是一维数组,在运行时,会将一个类的所有,分类,协议,属性重新规划,并且class_ro_t是不可读的。具体见 图-01。

值得注意的是class_data_bits_t一开始也是指向class_ro_t,在运行时,合并分类的时候,才将class_data_bits_t指向class_ro_t.
2 isa和superClass与类的关系
实例对象isa指向类对象,类对象isa指向元类对象,所有的元类对象isa指向基类的元类(报括基类的isa,指向自己)。
实例对象没有superClass,类对象superClass指向其父类,基类的superClass指向基类的类对象([NSObject class]).基类的superClass =nil;。
# define ISA_MASK 0x00007ffffffffff8ULL
这里的isa是指arm64之前的,若是arm64之后,则需要把isa &ISA_MASK,取出其中一段才是我们之前概念里面的isa指针。因为arm64之后,苹果有优化,Class isa 变成了 isa_t这个union公用体,里面不止是存了类对象,元类对象的地址,还存着有其他许多信息,比如nonpointer代表,bits里有一个bit代表这个isa是否是普通指针

3 cache_t
cache_t:调用过的方法列表。结构体里存着三个成员:struct bucket_t *_buckets//散列表、mask_t _mask;//散列表的长度-1 、ma s k_t _occupied;//已经缓存的方法数量。_bucket 里存两个成员:cache_key_t key;//SEL作为key IMP _imp //函数的内存地址。如 图-02:

往cache_t里存方法过程:
用方法的SEL(_key),即@selector(方法名)&_mask 得到一个索引,然后看buckets对应索引的位置有没有方法,没有的话,_key = @selector(方法名), _imp = 函数地址组成一个bucket存到对应索引的位置。若是一开始对应索引已经存值了,把索引-1,把bucket存到这里。若是每个索引位置都有bucket存着,则清空 buckets, mask_t乘以2,把bucket存到对应索引位置。
从cache_t里取方法过程:
用方法的SEL(_key),即@selector(方法名)&_mask 得到一个索引,然后根据索引从_buckets散列表里取出一个_bucket,把_bucket里的_key 和 @selector(方法名)对比,若是相等则返回方法,若是不相等则,把索引减1,往前查找,一直查到0,若是还找不到,则跳到最后,一直找到之前索引位置+1.还没有则返回null。
散列表(哈希表):用某种算法获取值当成索引获取value,存取数据,空间换时间。
查找方法过程:
先去一个类的cache_t里去查找,如果找不到则去methods方法列表里去找,找到的话就往cache_t里存,如果找不到,则通过superCalss指针找到它的父类,在父类里的cache_t里找,找不到则去方法列表里找,找到的话,往子类的cache_t里存(注意是自己的cache_t)。再找不到则通过父类的superCalss里去找,一直找到基类或者抛出异常。
class_data_bits_t & FAST_DATA_MASK 可以获得 图-04内容,其中methods是二维数组,存着许多method_list_t(一维数组),每个method_list_t可能是一个分类的所有方法的数组。或者类本身方法数组。method_list_t里存着许多个method_t,里面内容如图-05:

另:method结构

属性列表和协议列表与之类似。
注SEl :当作方法名方法序列号,里面首元素为char类型,因为把它的地址转成char就是字符串,结构体地址即是首元素地址。
内容仅供自己记录学习内容。
网友评论