美文网首页
iOS看源码:类的结构分析

iOS看源码:类的结构分析

作者: FireStroy | 来源:发表于2020-07-08 20:33 被阅读0次

    类的结构

    typedef struct objc_class *Class;
    typedef struct objc_object *id;
    
    struct objc_object {
    private:
        isa_t isa;
    public:
        //...很多方法
    }
    
    struct objc_class : objc_object {
       //Clas isa;        
       Class superclass;
       cache_t cache;        
       class_data_bits_t bits;
       class_rw_t *data() { 
            return bits.data();
        }
        void setData(class_rw_t *newData) {
            bits.setData(newData);
        }
        //…省略很多方法
    }
    

    Class对象的结构体内除了有继承自objc_objectClass isa;,还看到了熟悉的superclass。宁外还有cache_t cache;以及class_data_bits_t bits;这些重要的成员。

    • cache_t cache; 占用16个字节的内存空间
    struct cache_t {
        explicit_atomic<struct bucket_t *> _buckets;
        explicit_atomic<mask_t> _mask;
    #if __LP64__
        uint16_t _flags; 
    #endif
        uint16_t _occupied;
    
    • class_data_bits_t bits;占8个字节内存空间
    struct class_data_bits_t {
        uintptr_t bits;
        //...
    }
    
        class_rw_t *data() { 
            return bits.data();
        }
    

    可以获取到bits数据

    验证一下类的内存结构和信息的存放

    @interface MyClass : NSObject{
        NSString *myName;
    }
    @property(nonatomic,copy)NSString *youName;
    - (void)say;
    + (void)hello;
    @end
    
    @implementation MyClass
    - (void)say{
        NSLog(@"say");
    }
    
    + (void)hello{
        NSLog(@"hello");
    }
    @end
    
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            MyClass *myClass = [[MyClass alloc]init];
            NSLog(@"");
        }
        return 0;
    }
    
    myClass内存指针.jpg

    按照类的结构体定义来看 前8个字节存放的是isa 指向的应该是myClass这个实例对象的类对象MyClass 我们验证一下(0x00007ffffffffff8ULL是模拟器环境下的ISA_MASK对应的值):

    isa验证

    那么 接下来就要看看MyClass这个类对象内部存储:

    MyClass类对象
    注意上图中 $6MyClass$6isa还是MyClass 但是他们的指针地址已经不一样,因为类对象MyClassisa指向的是元类MyClass。那么 按照苹果给出的isa指向图 元类的isa指向的是根元类这里可以验证一下

    验证玩了对象的isa指向 现在来看看类的内存结构:
    MyClass的前8个字节是isa,再往后8个字节就是superclass
    再往后的16个字节就是cache,最后才是存放了类相关方法、属性等信息的bits。如下图所示


    通过调用bits->data()可以返回一个class_rw_t *结构体指针
    来解读一下这个结构体里面的内容:
    class_rw_t

    上图中的class_rw_t就是存放类的各种协议、属性、方法等的位置。
    具体如何获取请看源码简示:

    struct class_rw_t {
        uint32_t flags;
        uint16_t witness;
    #if SUPPORT_INDEXED_ISA
        uint16_t index;
    #endif
        explicit_atomic<uintptr_t> ro_or_rw_ext;
        Class firstSubclass;
        Class nextSiblingClass;
    
        const method_array_t methods() const {
               //...方法
        }
    
        const property_array_t properties() const {
              //...属性
        }
        const protocol_array_t protocols() const {
             //...协议
        }
        //...
    }
    

    简单查看一下属性:


    注意 成员变量在这里不能获取到而是通过ro()
    来获取class_ro_t *来获取:

    struct class_ro_t {
        uint32_t flags;
        uint32_t instanceStart;
        uint32_t instanceSize;
    #ifdef __LP64__
        uint32_t reserved;
    #endif
        const uint8_t * ivarLayout;
        const char * name;
        method_list_t * baseMethodList;
        protocol_list_t * baseProtocols;
        const ivar_list_t * ivars;
        const uint8_t * weakIvarLayout;
        property_list_t *baseProperties;
        method_list_t *baseMethods() const {
            return baseMethodList;
        }
        //...
    };
    

    这一节先写这么多

    相关文章

      网友评论

          本文标题:iOS看源码:类的结构分析

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