美文网首页
10期_iOS_类的本质(2)

10期_iOS_类的本质(2)

作者: 萧修 | 来源:发表于2023-08-14 01:45 被阅读0次

    同类型的对象可以创建多个,但是类只有一个

    而类在编译期创建,并只有一份。

    查看类的初始化,下面为clang之后的代码。

    int main(int argc, const char * argv[]) {
        /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool;
             CJPerson * person = ((CJPerson *(*)(id, SEL))(void *)objc_msgSend)((id)((CJPerson *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("CJPerson"), sel_registerName("alloc")), sel_registerName("init"));
            NSLog((NSString *)&__NSConstantStringImpl__var_folders_fg_3995175d2_v6g81lknk8jdwh0000gn_T_main_e6fa2f_mi_0,((Class (*)(id, SEL))(void *)objc_msgSend)((id)person, sel_registerName("class")));
        }    
        return 0;
    }
    
    

    获取类的通过objc_getClass

    源码文件中

    __OBJC_RW_DLLIMPORT struct objc_class *objc_getClass(const char *);
    
    typedef struct objc_class *Class;
    
    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
        ...
      }
    

    Class ISA注释了,继承自objc_object,ISA来自父类

    类的真正类型是objc_class,继承自objc_object(NSObject的底层结构),万物皆对象,类也是一个对象。

    类的数据结构

    ISA、supperclass、cache、bits

    • ISA
    • supperclass
    • cache_t cache
      方法缓存:方法涉及到,方法查找流程,缓存策略,动态扩容等
    struct cache_t {
        struct bucket_t *buckets() const;
        mask_t mask() const;
    }
    
    struct bucket_t {
    private:
        // IMP-first is better for arm64e ptrauth and no worse for arm64.
        // SEL-first is better for armv7* and i386 and x86_64.
    #if __arm64__
        explicit_atomic<uintptr_t> _imp;
        explicit_atomic<SEL> _sel;
    #else
        explicit_atomic<SEL> _sel;
        explicit_atomic<uintptr_t> _imp;
    #endif
    }
    

    buckets:装方法的桶子,里面存放方法的实现imp,根据方法编号sel生成key
    bucket_t:结构体指针,占用8个字节,

    • class_data_bits_t bits
      数据存放的地方,bits里面有data,data是从macgo读取的class_rw_t

    class_rw_t中结构体中有方法列表,属性列表,协议列表。里面的class_ro_t

    struct class_data_bits_t {
        class_rw_t* data() const {
            return (class_rw_t *)(bits & FAST_DATA_MASK);
        }
    }
    
    struct class_rw_t {
        const class_ro_t *ro() const {
            auto v = get_ro_or_rwe();
            if (slowpath(v.is<class_rw_ext_t *>())) {
                return v.get<class_rw_ext_t *>(&ro_or_rw_ext)->ro;
            }
            return v.get<const class_ro_t *>(&ro_or_rw_ext);
        }
        
        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};
            }
        }
    }
    
    struct class_ro_t {
        WrappedPtr<method_list_t, method_list_t::Ptrauth> baseMethods;
        protocol_list_t * baseProtocols;
        const ivar_list_t * ivars;
        property_list_t *baseProperties;
    }
    

    class_ro_t中有,方法列表,协议列表,实例变量列表,属性列表

    类添加的属性方法

    向类中实例变量,属性,方法,类方法

    • 成员变量存放在class_ro_t中的ivar_list
    • 属性在class_rw_t中的property_listclass_ro_t中的property_list_t都存着一份,并且会生成实例变量,和对应的方法
    • 方法在class_rw_t的method_array_tclass_ro_t中的的method_list_t都存着一份
    • 对象方法存放在类里面
    • 类方法存放在元类里面

    class_ro_t存储了当前类在编译期就已经确定的属性,方法,以及遵循的协议,而class_rw_t是运行时才确定,它会将class_ro_t的内容拷贝过去,然后再将当前类的分类方法这些属性,方法等拷贝其中

    相关文章

      网友评论

          本文标题:10期_iOS_类的本质(2)

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