五、isa走位 和 类结构分析

2020-09-09  本文已影响0人  KB_MORE

先附上经典图, 表示敬畏😸


看了好多遍的isa走位图
isa的走位
  1. 实例对象(Instance of Subclass)的isa 指向 类(class)

  2. 类对象(class) isa 指向 元类(Meta class)

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

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

superclass(继承关系)走位
  1. 类(subClass) 继承自 父类(superClass)

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

  3. 根类 继承自 nil,所以 根类NSObject可以理解为万物起源

  4. 子类元类(metal SubClass) 继承自 父类元类(metal SuperClass)

  5. 父类元类(metal SuperClass ) 继承自 根元类(Root metal Class

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

分析

LGPerson

@interface LGPerson : NSObject
+ (void)sayHello;
- (void)say666;
@end
#import "LGPerson.h"

@interface LGPerson ()
@property (nonatomic, copy) NSString *name;
@end
@implementation LGPerson{
    NSString *_hobby;
}
+ (void)sayHello{
    NSLog(@"sayHello");
}
- (void)say666{
    NSLog(@"say666");
}
@end

LGTeacher 继承LGPerson

#import "LGPerson.h"

@interface LGTeacher : LGPerson

@end

#import "LGTeacher.h"

@implementation LGTeacher

@end

        LGPerson *person = [LGPerson alloc];
        LGTeacher  *teacher = [LGTeacher alloc];

        NSLog(@"Hello, Person!  %@",person);
        NSLog(@"Hello, Teacher!  %@",teacher);
图片.png
图片.png

p/x : 打印person首地址
x/4gx :查看person内存情况: 第一个为isa指针地址
指针地址 & 0x00007ffffffffff8ULL: 获取类信息
isa走位
person -> LGPerson ->LGPerson(元类)->NSObject(根元类)->NSObject

类结构分析

LGPerson继承至NSObject

@interface NSObject <NSObject> {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-interface-ivars"
    Class isa  OBJC_ISA_AVAILABILITY;
#pragma clang diagnostic pop
}

NSObject的底层编译是NSObject_IMPL结构体,
其中 Classisa指针的类型,是由objc_class定义的类型,
objc_class是一个结构体。在iOS中,所有的Class都是以 objc_class为模板创建的`

struct NSObject_IMPL {
    Class isa;
};
typedef struct objc_class *Class;

查看源码已经被废除

图片.png
不过可以根据最后一行注释(/* Use Class instead of struct objc_class * */
)找到目前所用的class 图片.png 同理可查出 objc_class的父类objc_object 图片.png

【问题】objc_class 与 objc_object 有什么关系?

通过上述的源码查找以及main.cpp中底层编译源码,有以下几点说明:

【百度面试题】objc_object 与 对象的关系

【总结】 objc_object对象关系继承关系

总结

objc_class、objc_object、isa、object、NSObject等的整体的关系,如下图所示

image

到底类中有哪些信息呢?

根据前文提及的objc_class 的新版定义(objc4-781版本)如下,有以下几个属性

struct objc_class : objc_object {
    // Class ISA; //8字节
    Class superclass; //Class 类型 8字节
    cache_t cache;             // formerly cache pointer and vtable
    class_data_bits_t bits;    // class_rw_t * plus custom rr/alloc flags
    
    //....方法部分省略,未贴出
}

可以通过地址偏移获取bits里面的类信息, 首先我们还需要知道地址的偏移量

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个字节

获取bits

所以有上述计算可知,想要获取bits的中的内容,只需通过类的首地址平移32字节即可

以下是通过lldb命令调试的过程


图片.png

也可以打印属性列表


图片.png

以及存在ro里面的ivars


图片.png class_rw_t中的一部分重要信息 图片.png
上一篇下一篇

猜你喜欢

热点阅读