oc 基础 -rumtime-方法缓存

105 阅读1分钟

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) }