美文网首页IOS底层
iOS底层解析-----从isa指针看继承关系

iOS底层解析-----从isa指针看继承关系

作者: Mr丨Yang | 来源:发表于2019-02-27 17:12 被阅读88次

    NSObject对象的本质中提到对象中都存在isa指针,那么
    问题一:对象的isa指针指向哪里?
    问题二:OC的类信息存放在哪里?

    概述:
    Objective-C中的对象,简称OC对象,主要分为3种

    1. instance对象(实例对象)
    2. class对象(类对象)
    3. meta-class对象(元类对象)

    上一章节已说到类 alloc处理的的对象,每次调用alloc都会产生新的实例对象,占据不同的内存块。

    那么三种对象在内存中存储的信息有哪些?

    //实例对象 
    object1 object2 是NSObject 的实例对象,占据不同的内存块
    //在内存中存储的信息包括----->
    1. isa指针 
    2. 其它成员变量
    3. ……
    NSObject *object1 = [[NSObject alloc] init];
    NSObject *object2 = [[NSObject alloc] init];
       
    // objectClass1~ objectClass5都是NSObject的class对象,
    它们是同一个对象,每个类在内存中有且只有一个class对象
    //在内存中存储的信息包括----->
    1. isa指针 
    2. superclass指针
    3. 类的属性信息(@property)、类的对象方法信息(instance method)
    4. 类的协议信息(protocol)、类的成员变量信息(ivar)
    5. ……
    Class objectClass1 = [object1 class];
    Class objectClass2 = [object2 class];
    Class objectClass3 = object_getClass(object1);
    Class objectClass4 = object_getClass(object2);
    Class objectClass5 = [NSObject class];
    
     NSLog(@"%p %p",object1, object2);
            
      NSLog(@"%p %p %p %p %p",
                  objectClass1,
                  objectClass2,
                  objectClass3,
                  objectClass4,
                  objectClass5);
    
    // meta-class对象,元类对象
    将类对象当做参数传入,获得元类对象
    每个类在内存中有且只有一个meta-class对象
    meta-class对象和class对象在内存结构是一样的,但是用途不一样
    //在内存中存储的信息包括----->
    1. isa指针 
    2. superclass指针
    3. 类的类方法信息(class method)
    4. ……
    
     Class objectMetaClass = object_getClass(objectClass5);
     NSLog(@"objectMetaClass - %p %d", objectMetaClass, class_isMetaClass(objectMetaClass));
    
    以上代码所列结论可通过源码查找,字数问题不在阐述,只展示相对应的数据结构 数据结构.png

    既然已经知道三种对象所包含的内容,它们都包含isa指针,那么isa指针有什么作用?

    如下图 isa指针.png

    实例对象(instance)的isa指向类对象
    当调用对象方法时,通过实例对象(instance)的isa指针找到类对象(class),调用类对象(class)中的对象方法等进行实现

    类对象(class)的isa指针指向元类对象(meta-class)
    当调用类方法(class)时,通过类对象(class)的isa指针找到元类对象(meta-class),最后找到类方法的实现进行调用

    这样就很清晰的了解了代码中常见的方法调用原理

    //随手写的 套用以上isa指针原理
    //实例化对象
    Person *person = [Person alloc] init];
    [person test];//对象方法调用
    [Person test];//类方法调用
    
    

    那么如果类存在继承关系是如何调用的呢?
    我们从"isa指针图"中可以看出,在class 与 meta-class中存在superClass指针,那么看下图

    superClass指针.png

    从图中可以看出来sutdent类继承自Person Person继承自NSObject基类
    从继承的角度看,子类可以继承父类的方法,可以直接调用父类的方法,也可以重写父类的方法
    那么从指针的角度看呢?
    当Student的instance对象要调用Person对象方法时,会先通过isa找到Student的class,然后通过superClass找到Person的class,最后找到对象方法的实现进行调用

    可以理解为这样一个过程
    isa--->superClass--->superClass-->superClass==nil
    如果整个过程都没有找到,会报一个常见的经典错误
    unrecognized selector sent to class

    到这里是不是感觉可以从isa 指针来明白方法的调用,以及子类继承父类的时候,是怎样的一个调用过程
    那配上如下网上经典方法调用图片

    调用关系.png
    结合前面的笔记大概应该明白这幅图怎样的一个调用过程了,对图片做最后一个解释
    按照前面说的,meta-class中存在的是类方法,最后找到meta Root Class 类中,依然不存在该类方法,不应该是指针指向nil,而图片却指向class对象呢?

    如果Root Class方法中不存在对象方法指向nil
    如果存在对象方法,却可以调用成功。

    那就违背继承的原理,为什么我调用类方法,没找到却调用对象方法成功了

    这是因为OC 是基于C/C++实现的,它并没有严格意义上遵守面向对象的继承关系,因为它在运行时的时候最终会转化成
    objc_msgSend([xxx class],@selector(test))
    这样的消息传递的方式,它的方法并不在意你是类方法,还是对象方法。

    回答开始问题

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

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

    纯干货,喜欢的话,点赞以示鼓励

    下篇文章链接
    KVO与KVC原理

    相关文章

      网友评论

        本文标题:iOS底层解析-----从isa指针看继承关系

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