01isa
三种对象在内存中的结构,他们之间肯定是有联系的
截屏2020-10-19下午8.36.36.png
我们在调用方法的时候本质上是发消息,给这个对象发消息。而对象方法存在类对象中,类方法存在元类对象中,所以他们之间使用了isa来进行连接
-
instance的isa指向class
当调用对象方法时,通过instance的isa找到class,最后找到对象方法的实现进行调用 -
class的isa指向meta-class
当调用类方法时,通过class的isa找到meta-class,最后找到类方法的实现进行调用
02-class的superclass
很重要牵扯到方法调用,是用来找父类的,
我们首先创建两个类Person 和Student,让他们之间继承,加上NSObject一共会有3个类对象,
@interface Person:NSObject
@end
@interface Student:Person //16
@end
他们之间的关系
类对象之间的联系系
当Student的instance对象要调用Person的对象方法时,会先通过isa找到Student的class,然后通过superclass找到Person的class,最后找到对象方法的实现进行调用
03-meta-class的superclass
元类的superclass之间的关系和作用,Student的元类的superclass指针指向的是Person的元类对象,Person的元类的superclass指针指向的是NSObject的元类对象
元类关系
当Student的class要调用Person的类方法时,会先通过isa找到Student的meta-class,然后通过superclass找到Person的meta-class,最后找到类方法的实现进行调用
04-总结01.
对象之间的isa和superclass之间的关系instance的isa指向class
class的isa指向meta-class
meta-class的isa指向基类的meta-class
class的superclass指向父类的class
如果没有父类,superclass指针为nil
meta-class的superclass指向父类的meta-class
基类的meta-class的superclass指向基类的class
-
instance调用对象方法的轨迹
isa找到class,方法不存在,就通过superclass找父类 -
class调用类方法的轨迹
isa找meta-class,方法不存在,就通过superclass找父类,如果找到基类的元类也没有,他回去基类的类对象里面找这个方法,如果还是没有,就会报错unrecognized selector sent to
05总结02
如果自己的类对象和父类的类对象里面都有test方法,他会先调用自己类的方法,如果自己的类没有就会调用父类的方法,如果父类也没有这个类方法,但是有对象方法,那么它也可以调用成功,因为方法的调用本质就是发消息objc_senMessage(接受者,@selector(name));他只关心给谁发送了哪条消息,并不在乎是-或者+开头的方法
06isa细节
对象isa里面存的地址值就是他所指向的对象的地址,从64bit开始 isa需要进行一次位运算,才能计算出真实地址
isa计算方式
# if __arm64__
# define ISA_MASK 0x0000000ffffffff8ULL
# elif __x86_64__
# define ISA_MASK 0x00007ffffffffff8ULL
# else
# error unknown architecture for packed isa
# endif
如果我们想要看一下person的isa的值, 可以利用lldb调试工具操作,经过我们自己手动进行isa之间的位运算,法相,person的isa&isa_mask之后确实得到的就是Person类对象的地址(isa的地址)
isa计算验证
如果我们想要拿出类对象的isa指针,需要将这个类转成我们自制设计的结构体,因为原来不允许我们访问,所以根据我们计算,类对象和元类的isa也是对应的
类对象的isa和元类的isa
superclass这个指针是不是存在mask运算的,直接可以找到父类类对象的地址
superclass的关系
07class和metaClass的结构
证明类对象里面确实存放了属性信息,对象方法信息,协议信息
因为类对象都是一种objc_class类型的结构,所以这个结构体里面的信息,就说我们类对象在内存中存放的信息,通过我们下载的开源的源码,搜索objc_class找到新的结构体,在objc-runtime-new里面,这个里面的结构体也有继承,因为他是c++的结构体,他和类没有区别,class对象和meta-class对象本质上都是struct objc_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_rw_t *data() const {
return bits.data();
}
}
//class_rw_t rw=readwrite t=table
struct objc_class的结构大致为一下内容
objc_class的结构
如果我们想验证一下是否真的是在内存中的结构,我们可以自己模仿他的结构体写一个我们自己的,然后把他们的类对象转成我们自己的结构体进一步验证。
但是如果弄成一样的太耗时间,而且可能编译不通过,所以我们手动改了一些地方;如果我们想编译c++的文件,我们需要把文件后缀改成.mm。c++的结构体可以不带struct直接使用
对象的isa指针指向哪里?
instance对象的isa指向class对象
class对象的isa指向meta-class对象
meta-class对象的isa指向基类的meta-class对象
OC的类信息存放在哪里?
对象方法、属性、成员变量、协议信息,存放在class对象中
类方法,存放在meta-class对象中
成员变量的具体值,存放在instance对象
8 答疑
类对象和元类对象一直在内存中,知道程序结束才释放内存,当程序一启动就分配了内存。
实例对象里面的成员变量是具体的值,类对象里面的成员变量,是成员变量的信息。
网友评论