iOS看源码:类的结构分析

类的结构

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;
    }
    //...
};

这一节先写这么多

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容