美文网首页IOS开发
isa和superclass

isa和superclass

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

    01isa

    三种对象在内存中的结构,他们之间肯定是有联系的


    截屏2020-10-19下午8.36.36.png

    我们在调用方法的时候本质上是发消息,给这个对象发消息。而对象方法存在类对象中,类方法存在元类对象中,所以他们之间使用了isa来进行连接

    • instance的isa指向class
      当调用对象方法时,通过instance的isa找到class,最后找到对象方法的实现进行调用

    • class的isa指向meta-class
      当调用类方法时,通过class的isa找到meta-class,最后找到类方法的实现进行调用

    02-class的superclass

    很重要牵扯到方法调用,是用来找父类的,
    我们首先创建两个类Person 和Student,让他们之间继承,加上NSObject一共会有3个类对象,

    @interface Person:NSObject
    @end
    @interface Student:Person //16
    @end
    

    他们之间的关系


    类对象之间的联系系

    当Student的instance对象要调用Person的对象方法时,会先通过isa找到Student的class,然后通过superclass找到Person的class,最后找到对象方法的实现进行调用

    03-meta-class的superclass

    元类的superclass之间的关系和作用,Student的元类的superclass指针指向的是Person的元类对象,Person的元类的superclass指针指向的是NSObject的元类对象


    元类关系

    当Student的class要调用Person的类方法时,会先通过isa找到Student的meta-class,然后通过superclass找到Person的meta-class,最后找到类方法的实现进行调用

    04-总结01.

    对象之间的isa和superclass之间的关系

    instance的isa指向class
    class的isa指向meta-class
    meta-class的isa指向基类的meta-class

    class的superclass指向父类的class
    如果没有父类,superclass指针为nil
    meta-class的superclass指向父类的meta-class
    基类的meta-class的superclass指向基类的class

    • instance调用对象方法的轨迹
      isa找到class,方法不存在,就通过superclass找父类

    • class调用类方法的轨迹
      isa找meta-class,方法不存在,就通过superclass找父类,如果找到基类的元类也没有,他回去基类的类对象里面找这个方法,如果还是没有,就会报错 unrecognized selector sent to

    05总结02

    如果自己的类对象和父类的类对象里面都有test方法,他会先调用自己类的方法,如果自己的类没有就会调用父类的方法,如果父类也没有这个类方法,但是有对象方法,那么它也可以调用成功,因为方法的调用本质就是发消息objc_senMessage(接受者,@selector(name));他只关心给谁发送了哪条消息,并不在乎是-或者+开头的方法

    06isa细节

    对象isa里面存的地址值就是他所指向的对象的地址,从64bit开始 isa需要进行一次位运算,才能计算出真实地址


    isa计算方式
    # if __arm64__
    #   define ISA_MASK        0x0000000ffffffff8ULL
    
    # elif __x86_64__
    #   define ISA_MASK        0x00007ffffffffff8ULL
    # else
    #   error unknown architecture for packed isa
    # endif
    

    如果我们想要看一下person的isa的值, 可以利用lldb调试工具操作,经过我们自己手动进行isa之间的位运算,法相,person的isa&isa_mask之后确实得到的就是Person类对象的地址(isa的地址)


    isa计算验证

    如果我们想要拿出类对象的isa指针,需要将这个类转成我们自制设计的结构体,因为原来不允许我们访问,所以根据我们计算,类对象和元类的isa也是对应的


    类对象的isa和元类的isa

    superclass这个指针是不是存在mask运算的,直接可以找到父类类对象的地址


    superclass的关系

    07class和metaClass的结构

    证明类对象里面确实存放了属性信息,对象方法信息,协议信息
    因为类对象都是一种objc_class类型的结构,所以这个结构体里面的信息,就说我们类对象在内存中存放的信息,通过我们下载的开源的源码,搜索objc_class找到新的结构体,在objc-runtime-new里面,这个里面的结构体也有继承,因为他是c++的结构体,他和类没有区别,class对象和meta-class对象本质上都是struct objc_class类型

    struct objc_class : objc_object {
        // Class ISA;
        Class superclass;
        cache_t cache;             // formerly cache pointer and vtable
        class_data_bits_t bits;    // class_rw_t * plus custom rr/alloc flags
    
        class_rw_t *data() const {
            return bits.data();
        }
    }
    //class_rw_t  rw=readwrite t=table
    
    

    struct objc_class的结构大致为一下内容


    objc_class的结构

    如果我们想验证一下是否真的是在内存中的结构,我们可以自己模仿他的结构体写一个我们自己的,然后把他们的类对象转成我们自己的结构体进一步验证。
    但是如果弄成一样的太耗时间,而且可能编译不通过,所以我们手动改了一些地方;如果我们想编译c++的文件,我们需要把文件后缀改成.mm。c++的结构体可以不带struct直接使用

    对象的isa指针指向哪里?
    instance对象的isa指向class对象
    class对象的isa指向meta-class对象
    meta-class对象的isa指向基类的meta-class对象

    OC的类信息存放在哪里?
    对象方法、属性、成员变量、协议信息,存放在class对象中
    类方法,存放在meta-class对象中
    成员变量的具体值,存放在instance对象

    8 答疑

    类对象和元类对象一直在内存中,知道程序结束才释放内存,当程序一启动就分配了内存。
    实例对象里面的成员变量是具体的值,类对象里面的成员变量,是成员变量的信息。

    相关文章

      网友评论

        本文标题:isa和superclass

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