美文网首页
Runtime-方法

Runtime-方法

作者: 越天高 | 来源:发表于2020-10-26 10:29 被阅读0次

01class的结构

元类对象和元类的结构是一样的,他是一种特殊的类对象

struct objc_class : objc_object {
    // Class ISA;
    isa_t isa;
    Class superclass;
    cache_t cache;             // formerly cache pointer and vtable方法缓存
    class_data_bits_t bits; //用来获取具体的类信息
}
类的内存结构

class_rw_t里面的methods、properties、protocols是二维数组,是可读可写的,包含了类的初始内容、分类的内容


class_rw_t的内容

class_ro_t里面的baseMethodList、baseProtocols、ivars、baseProperties是一维数组,是只读的,包含了类的初始内容,类当初我们声明的方法和属性协议,


class_ro_t里面的结构

方法02-method

method_t就是对函数/方法的封装,他的源码封装为

struct method_t {
    SEL name; //函数名 选择器 他就是一个名字。
    const char *types; //编码(返回值类型参数类型)
    MethodListIMP imp;//指向函数的指针(函数地址)
}
  • IMP代表函数的具体实现


    IMP
  • SEL代表方法\函数名,一般叫做选择器,底层结构跟char *类似
    可以通过@selector()和sel_registerName()获得
    可以通过sel_getName()和NSStringFromSelector()转成字符串
    不同类中相同名字的方法,所对应的方法选择器是相同的
typedef struct objc_selector *SEL;
  • types包含了函数返回值、参数编码的字符串


    types

方法03-Type%20Encoding

- (void)test;

通过转成源码的结构体类型,打印出方法的types是里面是v16@0:8
v=void返回值,16所有参数的字节数@第一个参数(self)0开始位子;:第二个参数IMP,8参数从第8个字节开始,每个方法都有这两个默认的参数

  • iOS中提供了一个叫做@encode的指令,可以将具体的类型表示成字符串编码
    NSLog(@"%s",@encode(int));//i
    NSLog(@"%s",@encode(SEL));//:
    NSLog(@"%s",@encode(id));//@
    NSLog(@"%s",@encode(void));//v
类型转成字符1
类型转成字符2

04Cache_t

在objc_class结构体的里有个Cache_t 用来做方法缓存的

  • Class内部结构中有个方法缓存(cache_t),用散列表(哈希表)来缓存曾经调用过的方法,可以提高方法的查找速度。去缓存数组找的时候,他会先判断一下key是不是相同找的selector,如果相同就调用

因为假如一个方法要调用很多次的话,每次都进行isa遍历去查找,会很麻烦,性能比较低,所以,第一次调用的时候,把这个方法放到这个里面,不管这个方法之前在哪里都会给缓存到类对象的cache里面,方法缓存,下次通过isa找到类对象的时,调用的时候先到这个cache里面查找,候,有没有那个方法,没有的话再去按照之前的方式分层查找。


cache_t结构

key = @selector(personTest);
imp = personTest的地址

05散列表缓存方法

分析他去缓存中找的时候是怎么快速找到的,散列表里面装的也是数组一样的元素

//他是拿到key& _mask
@selector(studentTest)  & _mask = 4生成就是索引,这个值在他当初把方法放到缓存的时候就已经做好了。在往里面的放的时候,就是按照这个计算结果,将方法放到对应的位子,假设数组一开始为空的,那么他前面就是空的没有东西

@selector(studentTest2)  & _mask = 2,他就会把它放到2纳那个位子,牺牲内存空间,来提升访问速度,因为可能会产生空的位子
,左边的值无论怎么变都<=右边的mask
如果两个方法的地址值生成的索引是一样的。
他寸纯的时候就会将这个值-1;
取的时候如果发现key和想要的不一样,那就-1;
如果到0,还没有,他就变成mask再一次次-1;
假设数组的长度不够了,他就会扩容,一旦扩容,他会将缓存清空

哈希表,就是用一个函数根据传入的key,计算出一个索引,如果索引冲突了,再进某种操作-1+1或者其他来解决这个冲突


散列表

06查看方法缓存

平时调用过的方法,就会放到cache之中,这样做的好处就是下次再调用这个方法的时候可以更快捷的找到他。就算方法是在父类的类对象里面找到也会缓存到自己类对象的cache里面。
让我们测试的类转成自己写的结构体,

07查看方法缓存

通过调用他父类的以及父类的父类的方法,然后查看结构体的cache,可以发现她也会将那些方法也放到缓存之后

GoodStudent *person = [[GoodStudent alloc] init];

        sl_objc_class *personClass = (__bridge struct sl_objc_class *)[GoodStudent class];
        
        [person goodStudentTest];
        [person studentTest];
        [person personTest];
        [person goodStudentTest];
        NSLog(@"-------------------");
        
        cache_t cache = personClass->cache;
//        bucket_t *buckets = cache._buckets;
//
//        bucket_t bucket = buckets[(long long)@selector(studentTest) & cache._mask];
//        NSLog(@"%s %p", bucket._key, bucket._imp);
//
//        for (int i = 0; i <= cache._mask; i++) {
//            bucket_t bucket = buckets[i];
//            NSLog(@"%s %p", bucket._key, bucket._imp);
//        }
        
        NSLog(@"%s %p", @selector(personTest), cache.imp(@selector(personTest)));
        NSLog(@"%s %p", @selector(studentTest), cache.imp(@selector(studentTest)));
        NSLog(@"%s %p", @selector(goodStudentTest), cache.imp(@selector(goodStudentTest)));

cache里面确实存在着他的父类的额方法


打印缓存方法

相关文章

  • Runtime-原理

    runtime初探对象与方法的本质runtime-消息发送runtime-动态方法解析runtime-消息转发 r...

  • Runtime-方法

    01class的结构 元类对象和元类的结构是一样的,他是一种特殊的类对象 class_rw_t里面的methods...

  • runtime-整理中

    runtime-整理中

  • Runtime-方法交换

    在iOS开发中,有一种编程方式叫面向切面编程(AOP),这种编程最大好处是,在不修改源代码的前提下,在原有功能上添...

  • Runtime-获得方法

    Method class_getInstanceMethod(Class cls, SEL name) //获得指...

  • runtime-方法交换-实例

    需求:简单统一快速的给app里面所有的button修改字体颜色 #import "UIButton+NXButto...

  • RunTime-自动归档方法

    注意,实现NSCoding协议不能使用extension,因为指定构造器不能声明在extension中

  • Runtime-(四)方法缓存

    方法缓存的查找流程,实际上就是按照给定的SEL,在方法缓存列表中找到对应的bucket_t中的IMP。对应的流程就...

  • Runtime-(七)动态添加方法

    在说动态添加方法之前,我们先来看一个问题 Q: 使用performSelector:可能会遇到什么问题? 这个方法...

  • runtime-动态方法解析测试

    动态方法解析1 动态方法解析2

网友评论

      本文标题:Runtime-方法

      本文链接:https://www.haomeiwen.com/subject/ffkbmktx.html