likes
comments
collection
share

iOS 类的底层探索(上)

作者站长头像
站长
· 阅读数 54

分析类对象内存存在个数

首先,我们创建一个LGPerson类继承于NSObject 通过不同获取类对象的方法来进行验证

    Class class1 = [LGPerson class];
    Class class2 = [LGPerson alloc].class;
    Class class3 = object_getClass([LGPerson alloc]);
    
    NSLog(@"\n%p-\n%p-\n%p",class1,class2,class3);

打印结果:

iOS 类的底层探索(上)

我们发现 类对象有且只有一个。

isa 流程探索

我们继续用LGPerson这个类来继续如下操作

iOS 类的底层探索(上)

通过不断地打印isa,我们发现可以总结出:

p对象isa --> LGPerson 类对象 
LGPerson 类对象的 isa --> LGPerson 元类对象
LGPerson 元类对象 isa --> NSObject 根元类
NSObject 根元类 isa --> 自己

iOS 类的底层探索(上)

继承链

我们再来创建一个LGTeacher类继承于LGPerson,通过class_getSuperclass来获取父类

iOS 类的底层探索(上)

我们可以看到 LGTeacher->LGPerson->NSObject->nil

元类链

    Class teacherMetaClass = objc_getMetaClass("LGTeacher");
    NSLog(@"teacher 的元类 %@ - %p",teacherMetaClass,teacherMetaClass);
    
    Class personMetaClass = objc_getMetaClass("LGPerson");
    NSLog(@"person 的元类 %@ - %p",personMetaClass,personMetaClass);
    
    Class superTeacherMetaClass = class_getSuperclass(teacherMetaClass);
    NSLog(@"teacher 的元类的父类 %@ - %p",superTeacherMetaClass,superTeacherMetaClass);
    
    Class superPersonMetaClass = class_getSuperclass(personMetaClass);
    NSLog(@"person 的元类的父类 %@ - %p",superPersonMetaClass,superPersonMetaClass);
    
    Class nsobjectClass = object_getClass(NSObject.class);
    NSLog(@"nsobjectClass:%@ - %p",nsobjectClass,nsobjectClass);

打印结果如下:

iOS 类的底层探索(上)

从打印结果我们可以发现 LGTeacher的元类->LGPerson的元类->NSObject->nil

iOS 类的底层探索(上)

总结

通过以上的探索可以总结出经典的isa走位图

iOS 类的底层探索(上)

类结构的分析

首先分析Class,打开objc源码发现

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

  ...
}

我们发现类的底层实际上是一个objc_class结构体

内存偏移

现在我们要探索一下bits存储的数据,isa (8个字节)superclass(8个字节),cache_t(16字节),也就是总共偏移32个字节。

获取bits里面的methodLists

iOS 类的底层探索(上)

获取bits里面的propertyList

iOS 类的底层探索(上)

通过lldb找到了bit地址 通过源码查看class_data_bits_t结构

struct class_data_bits_t {
...
 class_rw_t* data() const {
        return (class_rw_t *)(bits & FAST_DATA_MASK);
    }
...
}

查看class_rw_t结构

struct 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 *>(&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};
        }
    }
...
}

properties()methods()这两个方法可以获取属性

总结

1.在底层实际上是一个结构体objc_classobjc_class实际上也是继承objc_object,所以实际上也是对象 2.此次 我们只是对对象的方法和属性的存储进行了探究,可以看出对象方法属性实际上存在类的class_data_bits_tclass_rw_t里面\

下一篇章将继续探索成员变量存储 类方法的存储

转载自:https://juejin.cn/post/7089052408852152327
评论
请登录