美文网首页
一、oc对象底层原理分析

一、oc对象底层原理分析

作者: iOS_进击的小学生 | 来源:发表于2019-04-03 20:48 被阅读0次

    一、OC对象的分类

    OC对象主要可以分为三种:
    instance对象(实例对象)
    class对象(类对象)
    meta-class对象(元类对象)

    1.instance对象就是通过类alloc出来的对象,每次调用alloc都会产生新的instance对象。object1和object2都是NSObject的instace对象(实例对象),但他们是不同的两个对象,并且分别占据着两块不同的内存。
    NSObjcet *object1 = [[NSObjcet alloc] init];
    NSObjcet *object2 = [[NSObjcet alloc] init];
    

    instance对象在内存中存储的信息包括:1.isa指针 2.其他成员变量。


    image.png

    那么一个NSObject对象占用多少内存?
    NSObjcet实际上是只有一个名为isa的指针的结构体,因此占用一个指针变量所占用的内存空间大小,如果64bit占用8个字节,如果32bit占用4个字节。

    2.每一个类在内存中有且只有一个class对象。可以通过打印内存地址证明
    Class objectClass1 = [object1 class];
    Class objectClass2 = [object2 class];
    Class objectClass3 = [NSObject class];
    // runtime
    Class objectClass4 = object_getClass(object1);
    Class objectClass5 = object_getClass(object2);
    NSLog(@"%p %p %p %p %p", objectClass1, objectClass2, objectClass3, objectClass4, objectClass5);
    

    class对象在内存中存储的信息主要包括:
    isa指针
    superclass指针
    类的属性信息(@property),类的成员变量信息(ivar)
    类的对象方法信息(instance method),类的协议信息(protocol)


    image.png
    成员变量的值时存储在实例对象中的,因为只有当我们创建实例对象的时候才为成员变赋值。但是成员变量叫什么名字,是什么类型,只需要有一份就可以了。所以存储在class对象中。
    3.元类对象 meta-class
    //runtime中传入类对象此时得到的就是元类对象
    Class objectMetaClass = object_getClass([NSObject class]);
    // 而调用类对象的class方法时得到还是类对象,无论调用多少次都是类对象
    Class cls = [[NSObject class] class];
    Class objectClass3 = [NSObject class];
    class_isMetaClass(objectMetaClass) // 判断该对象是否为元类对象
    NSLog(@"%p %p %p", objectMetaClass, objectClass3, cls); // 后面两个地址相同,
    说明多次调用class得到的还是类对象
    
    每个类在内存中有且只有一个meta-class对象。

    meta-class对象和class对象的内存结构是一样的,但是用途不一样,在内存中存储的信息主要包括:
    isa指针
    superclass指针
    类的类方法的信息(class method)

    meta-class对象和class对象的内存结构是一样的,所以meta-class中也有类的属性信息,类的对象方法信息等成员变量,但是其中的值可能是空的。
    image.png

    二、对象的isa指针指向哪里

    1.instance的isa指向class,当调用对象方法时,通过instance的isa找到class,最后找到对象方法的实现进行调用。
    2.class的isa指向meta-class
    当调用类方法时,通过class的isa找到meta-class,最后找到类方法的实现进行调用


    image.png

    3.当对象调用其父类对象方法的时候,又是怎么找到父类对象方法的呢?,此时就需要使用到class类对象superclass指针。

    当Student的instance对象要调用Person的对象方法时,会先通过isa找到Student的class,然后通过superclass找到Person的class,最后找到对象方法的实现进行调用,同样如果Person发现自己没有响应的对象方法,又会通过Person的superclass指针找到NSObject的class对象,去寻找响应的方法
    image.png

    4.当类对象调用父类的类方法时,就需要先通过isa指针找到meta-class,然后通过superclass去寻找响应的方法。

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

    最后又是这张静定的isa指向图,经过上面的分析我们在来看这张图,就显得清晰明了很多。


    image.png
    对isa、superclass总结

    1.instance的isa指向class
    2.class的isa指向meta-class
    3.meta-class的isa指向基类的meta-class,基类的isa指向自己
    4.class的superclass指向父类的class,如果没有父类,superclass指针为nil
    5.meta-class的superclass指向父类的meta-class,基类的meta-class的superclass指向基类的class
    6.instance调用对象方法的轨迹,isa找到class,方法不存在,就通过superclass找父类
    7.class调用类方法的轨迹,isa找meta-class,方法不存在,就通过superclass找父类
    本文面试题总结:

    一个NSObject对象占用多少内存?

    答:一个指针变量所占用的大小(64bit占8个字节,32bit占4个字节)
    对象的isa指针指向哪里?
    答:instance对象的isa指针指向class对象,class对象的isa指针指向meta-class对象,meta-class对象的isa指针指向基类的meta-class对象,基类自己的isa指针也指向自己。
    OC的类信息存放在哪里?
    答:成员变量的具体值存放在instance对象。对象方法,协议,属性,成员变量信息存放在class对象。类方法信息存放在meta-class对象。

    参考链接:https://www.jianshu.com/p/aa7ccadeca88

    相关文章

      网友评论

          本文标题:一、oc对象底层原理分析

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