美文网首页
OC底层05:类结构分析

OC底层05:类结构分析

作者: 木扬音 | 来源:发表于2020-09-20 15:20 被阅读0次

在谈及面向对象编程的时候,总是离不开 对象对象 是对客观事物的抽象, 是对 对象 的抽象。它们的关系是,对象 的实例,对象 的模板。
在OC中对象的信息存储在中,那么是以什么样的结果存在的呢,我们可以在objc的源码中找到下面代码,从中可以发现objc_class 是继承objc_object 的,也就是说 也是一个对象。这也是OC中万物皆对象的由来。因其继承自 objc_object ,自然默认就含有了 objc_object 的成员 isa

isa和继承

image.png

我们可以通过isa流程和继承关系图发现

isa的走向有以下几点说明:

  • 实例对象(Instance of Subclass)的 isa 指向类(class)

  • 类对象(class) isa 指向元类(Meta class)

  • 元类(Meta class)的isa 指向 根元类(Root metal class)

  • 根元类(Root metal class) 的isa 指向它自己本身,形成闭环,这里的根元类就是NSObject

superclass(即继承关系)的走向也有以下几点说明:

  • 之间 的继承关系:

    • 子类(subClass) 继承自 父类(superClass)

    • 父类(superClass) 继承自 根类(RootClass),此时的根类是指NSObject

    • 根类 继承自nil,所以根类即NSObject可以理解为万物起源,即无中生有

  • 元类也存在继承,元类之间的继承关系如下:

    • 子类的元类(metal SubClass) 继承自 父类的元类(metal SuperClass)

    • 父类的元类(metal SuperClass) 继承自 根元类(Root metal Class)

    • 根元类(Root metal Class) 继承于 根类(Root class),此时的根类是指NSObject

-【注意】实例对象之间没有继承关系,之间有继承关系

/// Represents an instance of a class.
struct objc_object {
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;
};
struct objc_class : objc_object {
    // Class ISA;//8字节
    Class superclass; //8字节
    cache_t cache; //8字节            // formerly cache pointer and vtable
    class_data_bits_t bits;    // class_rw_t * plus custom rr/alloc flags
}
  • isa:关于isa的在[OC底层04:isa和类的关联],(https://www.jianshu.com/p/ad042414e5e4)可以找到答案,继承自objc_objectisa,占8字节
  • superclass:指向父类,依旧是Class类型,所以也占8字节
  • cache: 方法缓存列表,存储了最近调用的方法
  • bitsclass_data_bits_t类型,存储详细的类信息
    objc_class、objc_object、isa、object、NSObject

cache_t

我们进入cache_t,发现主要有如下几个属性

struct cache_t {
#if CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_OUTLINED
    explicit_atomic<struct bucket_t *> _buckets; // 是一个结构体指针类型,占8字节
    explicit_atomic<mask_t> _mask; //是mask_t 类型,而 mask_t 是 unsigned int 的别名,占4字节
#elif CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_HIGH_16
    explicit_atomic<uintptr_t> _maskAndBuckets; //是指针,占8字节
    mask_t _mask_unused; //是mask_t 类型,而 mask_t 是 uint32_t 类型定义的别名,占4字节
    
#if __LP64__
    uint16_t _flags;  //是uint16_t类型,uint16_t是 unsigned short 的别名,占 2个字节
#endif
    uint16_t _occupied; //是uint16_t类型,uint16_t是 unsigned short 的别名,占 2个字节

通过计算cache_t中属性大小为16字节
所以我们可以通过获取的首地址,通过平移32字节来获取bits中的内容

获取bits

准备工作

定义一个继承自NSObject的类YPPerson

@interface YPPerson : NSObject
{
    NSString *hobby;
}
@property (nonatomic, copy) NSString *yp_name;
- (void)sayHello;
+ (void)sayBye;
@end

@implementation YPPerson
- (void)sayHello{
}

+ (void)sayBye{
}
@end

通过lldb调试打印bits信息

image.png

获取属性列表

class_data_bits_t方法class_rw_t,点进去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};
        }
    }

    const protocol_array_t protocols() const {
        auto v = get_ro_or_rwe();
        if (v.is<class_rw_ext_t *>()) {
            return v.get<class_rw_ext_t *>()->protocols;
        } else {
            return protocol_array_t{v.get<const class_ro_t *>()->baseProtocols};
        }
    }

所以我们在刚刚获取到的bits信息基础上,通过class_rw_t提供的方法,我们可以继续打印出属性列表

获取属性列表
  • p $3.properties()命令中的propertoes方法是由class_rw_t提供的,方法中返回的实际类型为property_array_t(数组)

  • 由于list的类型是property_list_t,是一个指针,所以通过p *$5获取内存中的信息,同时也证明bits中存储了property_list,即属性列表

  • p $6.get(1),获取YPPerson中的成员变量, 发现会报错,提示数组越界了,说明 property_list 中只有一个属性yp_name

获取方法列表

image.png
  • 通过 p $4.methods()获得具体的方法列表的list结构,其中methods也是class_rw_t提供的方法

  • 通过打印的count = 4可知,存储了4个方法,可以通过p $7.get(i)内存偏移的方式获取单个方法,i 的范围是0-3

  • 如果在打印 p $7.get(4),获取第五个方法,也会报错,提示数组越界

相关文章

  • OC底层05:类结构分析

    在谈及面向对象编程的时候,总是离不开 对象 与 类 。对象 是对客观事物的抽象,类 是对 对象 的抽象。它们的关系...

  • OC底层_类结构分析

    类和类结构分析 类的分析 元类 在如下代码中断点调试: 元类是系统给的,其定义和创建都是由编译器完成,在这个过程中...

  • iOS 类原理探索:类的结构分析

    OC 类原理探索 系列文章 OC 类原理探索:类的结构分析 OC 类原理探索:类结构分析补充[https://ju...

  • iOS底层原理08:类结构分析——bits属性

    iOS底层原理07:类 & 类结构分析[https://www.jianshu.com/p/05f725a5ccb...

  • iOS底层初探

    OC底层实现原理 oc对象以及类的是底层实现 首先,通过数据结构的特性可以猜测类的底层应该是结构体这种数据结构,因...

  • objc_class 中 cache 原理分析

    OC底层原理学习[https://www.jianshu.com/nb/47790292] 回顾类的结构分析中[h...

  • OC底层原理--类结构分析

    通过上一篇文章对isa的分析,我们知道了所有的对象都包含isa,并且isa存储了类的相关信息,所以这篇文章我们主要...

  • OC底层-类结构体分析

    前言 上一篇已经分析了isa的内部结构,这篇文章我们主要来分析下objc_class的内部结构,以及如何验证。 探...

  • OC底层原理06-cache_t探究

    iOS--OC底层原理文章汇总 前言 本文主要探索cache_t * cache结构内容,分析它在类的结构中扮演了...

  • OC底层原理06-isa流程图

    一、回顾 上一期OC底层原理05-isa结构分析中,我们在GomuPerson的实例对象person的地址中,拿到...

网友评论

      本文标题:OC底层05:类结构分析

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