codeER.teciOS收藏

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

2021-06-17  本文已影响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 指向基类

总结

上一篇下一篇

猜你喜欢

热点阅读