系统底层源码分析(16)——类的本质

  1. 类的本质其实也是结构体:
struct objc_class : objc_object {
    // Class ISA; // 8
    Class superclass; // 8
    cache_t cache;    // 16          // formerly cache pointer and vtable
    class_data_bits_t bits;    // class_rw_t * plus custom rr/alloc flags
    //内存偏移32字节可以得到bits
    class_rw_t *data() { 
        return bits.data();
    }
    ...
}
struct objc_object {
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;
};
  • objc_class继承了objc_object,所以类其实也是一个对象。类在内存里只存在一份, 继承关系只存在于类之间, 而不存在于对象之间。
  1. 了解了类的结构,我们可以通过内存偏移(共需偏移32字节),在控制台打印得到bits的数据,从而可以知道保存属性和方法的地方:
struct class_rw_t {
    // Be warned that Symbolication knows the layout of this structure.
    uint32_t flags;
    uint32_t version;

    const class_ro_t *ro;

    method_array_t methods;
    property_array_t properties;
    protocol_array_t protocols;
    ...
}
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;
    }
};
  • 验证
@interface LGPerson : NSObject
{
    NSString *hobby;
}
@property (nonatomic, copy) NSString *nickName;

- (void)sayHello;
+ (void)sayHappy;
@implementation LGPerson
- (void)sayHello{
    NSLog(@"Hello!");
}
+ (void)sayHappy{
    NSLog(@"Happy!");
}
1.打印class的内存结构
//2.内存偏移
0x1000023b0 + 0x20 = 0x1000023d0
3.转换类型打印bits
4.获取data()
5.查看class_rw_t结构
6.打印观察是否有属性
7.获取class_ro_t
8.属性
9.大括号里的成员变量
10.生成带有下划线的属性名
11.实例方法
12.生成的setter和getter
  1. 通过isa在类对象中找到元类,打印元类的 baseMethodsList

所以实例方法存在类的baseMethodList中,而类方法存在元类的baseMethodList中。

下一篇:类的cache

你可能感兴趣的:(系统底层源码分析(16)——类的本质)