ro_t { method_t { SEL name // 函数名 const char *types //编码 返回值类型 参数类型 IMP imp 函数指针 } }
IMP 代表函数的具体实现 SEL 嗲表方法/函数名 一半叫做选择器,地城结构和char *类似
可以通过@Selector() 和sel_registerName() 获得 可以通过 sel_getName 和 NSStringFromSeletor () 转换成字符串 不同类中相同的名字方法 所对应的方法选择器是相同的
typers 包含编码 返回值类型 参数类型 @
[person test];
- (void)test:self(id)self cmd:(SEL)cmd;
转译成types 是
v16@0:8
返回值 参数一 参数二 参数三
@ 是 id 类型
i 是 int类型
: 是 seleter()
* 是 char*
# 是 Class
` class { chche_t chache; // 方法缓存 曾经调用过的结构,提高方法查找速度,散列表的形势存储 }
static { bucket_t { //散列表 cache_key_t _key; //SEL 作为key #selector(tast); IMP _imp; // 函数的地址指针 } mask_t _mask; // 散列表的长度 - 1 mask_t _occupied; // 已经缓存的方法数量 }
散列表的数据原理
查找速度会提高 java 是用求余 % 算 取 @selector(test) &9 mask = 索引 = 4 得到方法
放 @selector(test) &9 mask = 索引 = 4 存放到此处
通过位运算 得到索引 牺牲内存空间换时间 _mask 方法数量最大不会超过mask
如果根据mask 生成的索引是一样的 怎么解决 ?
使用 next 减一 , 一直到找到空位
_mask 是动态的,可以增加 old ✖️2
变得时候会清空缓存
查看缓存
person test1]; person test2]; person test3];
cache_t cache - personClass->cache;
buckte_t *bukets = cache.buckets;
for (int i = 0 , i <= cache._mask, i ++) { bucket_t bucket = cuckets[i]; nslog(@"%s, %p", bucket._key, bucket._imp) }