美文网首页codeER.teciOS收藏
iOS底层-类的底层原理(一)

iOS底层-类的底层原理(一)

作者: 沉淀纷飞 | 来源:发表于2021-06-17 18:02 被阅读0次

案例分析


1、通过终端cd 到main.m文件所在目录
2、终端输入xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main64.cpp 编译会得到一个c++文件(具体问什么这么做呢,可参考iOS底层-对象的本质

查看编译后的文件,我们可以得出实例对象实质为结构体,该结构体包含类指针和成员变量。

从图中可以看出NSObject也是objc_object类型的结构体,其内部一样包含isa指针和其他成员变量。在内存中isa地址就是instance的地址,其他成员变量依次排在后面。

打印结果如下

从打印结果中可以发现class1和class2的地址一样,class3、class4和class5的地址一样。
通过苹果官网下载objc源码,从源码中我们可以找到Class的源码实现。

我们可以得出结论Classobjc_class的结构体指针。那么objc_classobjc_object的内部是怎么实现的呢?
struct objc_class : objc_object {
  objc_class(const objc_class&) = delete;
  objc_class(objc_class&&) = delete;
  void operator=(const objc_class&) = delete;
  void operator=(objc_class&&) = delete;
    // 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
    ...代码太长省略
struct objc_object {
private:
    isa_t isa;

public:

    // ISA() assumes this is NOT a tagged pointer object
    Class ISA(bool authenticated = false);

    // rawISA() assumes this is NOT a tagged pointer object or a non pointer ISA
    Class rawISA();

    // getIsa() allows this to be a tagged pointer object
    Class getIsa();
    
    uintptr_t isaBits() const;
    ...代码太长省略

从源码从可以看到类中class_rw_t存储了变量、方法列表、协议列表、版本等信息。

struct class_rw_t {
    // Be warned that Symbolication knows the layout of this structure.
    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;

private:
    // 部分代码已省略
    // 方法列表
    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 *>(&ro_or_rw_ext)->methods;
        } else {
            return method_array_t{v.get<const class_ro_t *>(&ro_or_rw_ext)->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 *>(&ro_or_rw_ext)->properties;
        } else {
            return property_array_t{v.get<const class_ro_t *>(&ro_or_rw_ext)->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 *>(&ro_or_rw_ext)->protocols;
        } else {
            return protocol_array_t{v.get<const class_ro_t *>(&ro_or_rw_ext)->baseProtocols};
        }
    }
};

下面我们通过案例结合lldb分析类、元类和根元类


我们可以得到类对象isa指向的类对象我们称之为`元类。实例方法存储在类对象中,类方法存储在元类对象中。对象、类、元类我们一般通过下面的关系图说明

由图可见元类的isa 指向基类的元类。基类的元类的 superclass 指向基类

总结

  • 类的本质是对象
  • 类对象是一种数据结构,类存储的基本信息包含类大小、名称、版本、继承层次和消息与函数的映射表
  • 对象方法存放在类里面
  • 类方法存放在元类里面
  • 成员变量存放在class_ro_t中的ivar_list_t
  • 属性在class_rw_t中的property_array_tclass_ro_t中的的property_list_t都存着一份,并且会生成实例变量,和对应的方法
  • 方法在class_rw_t中的method_array_tclass_ro_t中的的method_list_t都存着一份
  • instance对象的isa指向Class对象
  • Class对象的isa指向meta-class对象
  • meta-class对象的isa指向基类的meta-class对象

相关文章

网友评论

    本文标题:iOS底层-类的底层原理(一)

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