美文网首页OC 底层原理笔记
13 runtime-isa-Class的结构详解

13 runtime-isa-Class的结构详解

作者: zysmoon | 来源:发表于2020-01-20 14:41 被阅读0次
    isa指针图解
    1653926-62a8c73af51e4446.png

    代码例子佐证 - 实例对象isa验证

    #import <Foundation/Foundation.h>
    #import <objc/runtime.h>
    
    // MJPerson
    @interface CSPerson : NSObject {
    @public
        int _age;
    }
    @property (nonatomic, assign) int no;
    - (void)personInstanceMethod;
    + (void)personClassMethod;
    @end
    
    @implementation CSPerson
    - (void)test {
    }
    - (void)personInstanceMethod {
    }
    + (void)personClassMethod {
    }
    @end
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            // CSPerson类对象的地址:0x0000000100001240
            // CSPerson实例对象的isa:0x001d800100001241
            // isa(0x001d800100001241) & ISA_MASK(0x0000000ffffffff8):0x0000000100001240
    
            CSPerson *person = [[CSPerson alloc] init];
    
            Class personClass = [CSPerson class];
    
            Class personMetaClass = object_getClass(personClass);
    
            NSLog(@"%p %p %p", person, personClass, personMetaClass);
        }
        return 0;
    }
    
    

    打印结果

    1653926-ac1d7ff4d011e1b9.png

    从打印结果我们可以知道实例对象的isa指针 & ISA_MASK等于类对象的地址

    代码例子佐证 - 类对象isa验证
    CSPerson代码还是使用上述代码,只是增加一个结构体

    struct cs_objc_class {
        Class isa;
    };
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            // CSPerson类对象的地址:0x001d800100001219
            // CSPerson元类对象的地址: 0x0000000100001218
            // isa(0x001d800100001219) & ISA_MASK(0x0000000ffffffff8) = 0x0000000100001218
    
            Class personClass = [CSPerson class];
    
            struct cs_objc_class *personClass2 = (__bridge struct cs_objc_class *)(personClass);
    
            Class personMetaClass = object_getClass(personClass);
    
            NSLog(@"%p %p %p", person, personClass, personMetaClass);
        }
        return 0;
    }
    
    

    输出结果

    1653926-f83d1ced16bf5d38.png

    从打印结果我们可以知道类对象的isa指针 & ISA_MASK等于元类对象的地址

    superclass

    代码例子佐证 - 新增CSStudent类,cs_objc_class结构体

    // CSStudent
    @interface CSStudent : CSPerson {
    @public
        int _weight;
    }
    @property (nonatomic, assign) int height;
    - (void)studentInstanceMethod;
    + (void)studentClassMethod;
    @end
    
    @implementation CSStudent
    - (void)test{
    }
    - (void)studentInstanceMethod{
    }
    + (void)studentClassMethod{
    }
    @end
    
    struct cs_objc_class {
        Class isa;
        Class superclass;
    };
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            // 3\. superclass
            struct cs_objc_class *personClass = (__bridge struct cs_objc_class *)([CSPerson class]);
            struct cs_objc_class *studentClass = (__bridge struct cs_objc_class *)([CSStudent class]);
    
            NSLog(@"%p %p", personClass, studentClass);
        }
        return 0;
    }
    
    

    运行结果

    1653926-852553024882f13f.png

    从打印结果可知,类对象的superclass指向元类对象地址

    项目连接地址 - Isa-class-detail

    struct objc_class

    1653926-4b79e8aa021f509c.png
    • class、meta-class对象的本质结构都是struct objc_class

    窥探struct objc_class的结构

    1653926-6ff583180e68579d.png

    代码佐证
    引入#import "MJClassInfo.h"文件,然后编写类

    #import <Foundation/Foundation.h>
    #import <objc/runtime.h>
    #import "MJClassInfo.h"
    
    // CSPerson
    @interface CSPerson : NSObject {
    @public
        int _age;
    }
    @property (nonatomic, assign) int no;
    - (void)personInstanceMethod;
    + (void)personClassMethod;
    @end
    
    @implementation CSPerson
    - (void)test {
    }
    - (void)personInstanceMethod {
    }
    + (void)personClassMethod {
    }
    @end
    
    // CSStudent
    @interface CSStudent : CSPerson {
    @public
        int _weight;
    }
    @property (nonatomic, assign) int height;
    - (void)studentInstanceMethod;
    + (void)studentClassMethod;
    @end
    
    @implementation CSStudent
    - (void)test{
    }
    - (void)studentInstanceMethod{
    }
    + (void)studentClassMethod{
    }
    @end
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            CSStudent *stu = [[CSStudent alloc] init];
            stu->_weight = 10;
    
            mj_objc_class *studentClass = (__bridge mj_objc_class *)([CSStudent class]);
            mj_objc_class *personClass = (__bridge mj_objc_class *)([CSStudent class]);
    
            class_rw_t *studentClassData = studentClass->data();
            class_rw_t *personClassData = personClass->data();
    
            class_rw_t *studentMetaClassData = studentClass->metaClass()->data();
            class_rw_t *personMetaClassData = personClass->metaClass()->data();
    
            NSLog(@"1111");
        }
        return 0;
    }
    
    

    运行结果分析

    • mj_objc_class结构
    1653926-b9ec96bb4d0de319.png
    • 类对象mj_objc_class结构
    1653926-c1ffe02b0764ab56.png
    • 元类对象mj_objc_class结构
    1653926-1326b22be66469ef.png

    面试题

    1.对象的isa指针指向哪里?
    • instance对象的isa指向class对象
    • class对象的isa指向meta-class对象
    • meta-class对象的isa指向基类的meta-class对象
    2.OC的类信息存放在哪里?
    • 对象方法、属性、成员变量、协议信息,存放在class对象中
    • 类方法,存放在meta-class对象中
    • 成员变量的具体值,存放在instance对象

    本文参考:
    路飞_Luck (https://www.jianshu.com/p/07f7b96bb03f)
    以及借鉴MJ的教程视频
    非常感谢.


    项目连接地址 - isa-class-struct

    相关文章

      网友评论

        本文标题:13 runtime-isa-Class的结构详解

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