iOS底层学习19 -- runtime方法缓存
2020-10-21 本文已影响0人
恋空K
当我们第一次去调用一个方法的时候,就会直接将这个方法扔到cache_t cache里面去,也就是缓存里面已经有这个方法了。下次在调用这个方法的时候,通过isa找到类对象的时候,会直接在类对象的cache_t cache里面找到这个方法。

假如person调用一个方法,这个方法在基类里面,第一次调用这个方法的时候(缓存里面肯定是没有的),会一层一层的往上找,在基类找到后,会把方法缓存到person类对象的cache_t cache里面,下次person在调用该方法的时候,会直接从perosn类对象的cache_t cache里面去调用
struct bucket_t * _buckets; // 散列表(是个数组,里面装的是这种struct bucket_t结构体,这个数组里面就缓存着我们的方法)
已存方法的数量是小于等于散列表长度的。


在一个对象里面,@selector()跟方法实现肯定是一对一的,一对一的话就是散列表,就跟我们的字典一样,一对一的。
散列表原理:
散列表底层数据结构就是一个数组。


当,当前的散列表缓满了,需要扩容的时候,会先清掉原先的缓存。新的空间是原来的两倍。散列表的效率比数组遍历高,就是以空间换时间。散列表开始就会给一定的内存空间,而不是存一个方法进去,就将内存扩大一点。
调用方法的时候,是先去类对象的cache_t cache里面查找,没有再去calss_wr_t里面的方法列表查找,在方法列表找到后,就调用方法,并把这个方法放到cache_t cache里面去。从父类里面的cache_t cache找到了这个方法,就调用方法,同时也是会把这个方法放到自己的cache_t cache里面去
调用的是哪个的init方法,缓存的就是哪个的init方法。

两个不同的SEL & _mask 得到的值有可能是一样的。

