OC 类的结构分析

网络中有个关于类的关系的图
isa流程图.png

图中虚线部分是isa的的继承关系
证明如下图
image.png

  1. 对象->类
//打印16进制person的内存地址
(lldb) p/x person
(LGPerson *) $26 = 0x00000001006e8400
//读取person的内存地址
(lldb) x/4gx 0x00000001006e8400
0x1006e8400: 0x001d8001000020f1 0x0000000000000000
0x1006e8410: 0x00000001006e84e0 0x00000001006e8720
//isa指针与上0x00007ffffffffff8ULL得到类信息
(lldb) p/x 0x001d8001000020f1 & 0x00007ffffffffff8ULL
//得到类地址
(unsigned long long) $27 = 0x00000001000020f0
(lldb) po 0x00000001000020f0
LGPerson

其中0x001d8001000020f1是类的isa指针
2. 类->元类

//读取类的地址
(lldb) x/4gx 0x00000001000020f0
0x1000020f0: 0x00000001000020c8 0x0000000100334140
0x100002100: 0x000000010032e410 0x0000801000000000
(lldb) p/x 0x00000001000020c8 & 0x00007ffffffffff8ULL
//元类地址
(unsigned long long) $29 = 0x00000001000020c8
(lldb) po 0x00000001000020c8
LGPerson

其中0x00000001000020c8是元类的isa指针
3. 元类->根元类

//读取元类的内存地址
(lldb) x/4gx 0x00000001000020c8
0x1000020c8: 0x00000001003340f0 0x00000001003340f0
0x1000020d8: 0x00000001006420f0 0x0004e03100000007
(lldb) po 0x00000001003340f0
NSObject

其中0x00000001003340f0是根元类的isa指针

  1. 根元类->根元类
(lldb) p/x 0x00000001003340f0 & 0x00007ffffffffff8ULL
(unsigned long long) $32 = 0x00000001003340f0
(lldb) x/4gx 0x00000001003340f0
0x1003340f0: 0x00000001003340f0 0x0000000100334140
0x100334100: 0x00000001006e6a50 0x0004e03100000007
(lldb) po 0x00000001003340f0
NSObject

类的继承
在objc-private.h中的objc_object是根对象

struct objc_object {
private:
    isa_t isa;
public:
    // ISA() assumes this is NOT a tagged pointer object
    Class ISA();
    省略号
};

objc_class也是继承自objc_object

struct objc_class : objc_object {
    // Class ISA;
    Class superclass;
    cache_t cache;             // formerly cache pointer and vtable
    class_data_bits_t bits;    // class_rw_t * plus custom rr/alloc flags
    省略号
}

objc的源码地址
所以objc_object是万物的根源。所有的类都是由它的模板而来。上层通过底层objc的提供的方法创建对象。

类的结构

源码在objc-runtime-new.h中

struct objc_class : objc_object {
    // Class ISA;      isa指针8个字节
    Class superclass;        //父类8个字节
    cache_t cache;             // formerly cache pointer and vtable 16
    class_data_bits_t bits;    // class_rw_t * plus custom rr/alloc flags
    class_rw_t *data() const {
        return bits.data();
    }
    //省略号
  //下面的都是方法
}

isa8个字节,父类superclass8个字节,cache占16个,要读取bits需要从类的地址偏移32位读取。
创建类

@interface LGPerson : NSObject

@property(nonatomic,copy) NSString *nickName;
@property(nonatomic,copy) NSString *identifer;

-(void)sayHello;

+(void)sayWorld;

@end

#import "LGPerson.h"

@implementation LGPerson
-(void)sayHello{
}
+(void)sayWorld{
}
@end

image.png
如图

  1. 获取类的首地址0x0000000100002248,objc_class是一个结构体,其中isa8个字节,父类superclass8个字节,cache占16个,要读取bits需要从类的地址偏移32位读取。cache通过查看其源码得知。
  2. 此时$1为bits,调用其data()方法,返回一个class_rw_t类型的数据$3,返回的数据信息不熟悉。查看class_rw_t源码有如下
    //方法
    const method_array_t methods() const {
        auto v = get_ro_or_rwe();
        if (v.is<class_rw_ext_t *>()) {
            return v.get<class_rw_ext_t *>()->methods;
        } else {
            return method_array_t{v.get<const class_ro_t *>()->baseMethods()};
        }
    }
    //属性
    const property_array_t properties() const {
        auto v = get_ro_or_rwe();
        if (v.is<class_rw_ext_t *>()) {
            return v.get<class_rw_ext_t *>()->properties;
        } else {
            return property_array_t{v.get<const class_ro_t *>()->baseProperties};
        }
    }

  1. 输出class_rw_t的properties()方法
(const property_array_t) $4 = {
  list_array_tt<property_t, property_list_t> = {
     = {
      list = 0x00000001000021d0
      arrayAndFlag = 4294975952
    }
  }
}
(lldb) p $4.list
(property_list_t *const) $5 = 0x00000001000021d0
(lldb) p *$5
(property_list_t) $6 = {
  entsize_list_tt<property_t, property_list_t, 0> = {
    entsizeAndFlags = 16
    count = 2
    first = (name = "nickName", attributes = "T@\"NSString\",C,N,V_nickName")
  }
}

这个properties()方法可以获取我们在LGPerson中定义的属性如下图
image.png

于此同时我们可以获取method
image.png

  1. 调用class_rw_t ($3)的methods()方法,返回方法信息
  2. 读取list中的信息,发现有6个方法,
    • 在LGPerson中定义的方法sayHello
    • 属性nikName和identifier的get和set方法
    • .cxx_destruct方法
  3. 发现我们定义的类方法并不存在这个metho_list中。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值