在NSObject对象的本质中提到对象中都存在isa指针,那么
问题一:对象的isa指针指向哪里?
问题二:OC的类信息存放在哪里?
概述:
Objective-C中的对象,简称OC对象,主要分为3种
- instance对象(实例对象)
- class对象(类对象)
- meta-class对象(元类对象)
上一章节已说到类 alloc处理的的对象,每次调用alloc都会产生新的实例对象,占据不同的内存块。
那么三种对象在内存中存储的信息有哪些?
//实例对象
object1 object2 是NSObject 的实例对象,占据不同的内存块
//在内存中存储的信息包括----->
1. isa指针
2. 其它成员变量
3. ……
NSObject *object1 = [[NSObject alloc] init];
NSObject *object2 = [[NSObject alloc] init];
// objectClass1~ objectClass5都是NSObject的class对象,
它们是同一个对象,每个类在内存中有且只有一个class对象
//在内存中存储的信息包括----->
1. isa指针
2. superclass指针
3. 类的属性信息(@property)、类的对象方法信息(instance method)
4. 类的协议信息(protocol)、类的成员变量信息(ivar)
5. ……
Class objectClass1 = [object1 class];
Class objectClass2 = [object2 class];
Class objectClass3 = object_getClass(object1);
Class objectClass4 = object_getClass(object2);
Class objectClass5 = [NSObject class];
NSLog(@"%p %p",object1, object2);
NSLog(@"%p %p %p %p %p",
objectClass1,
objectClass2,
objectClass3,
objectClass4,
objectClass5);
// meta-class对象,元类对象
将类对象当做参数传入,获得元类对象
每个类在内存中有且只有一个meta-class对象
meta-class对象和class对象在内存结构是一样的,但是用途不一样
//在内存中存储的信息包括----->
1. isa指针
2. superclass指针
3. 类的类方法信息(class method)
4. ……
Class objectMetaClass = object_getClass(objectClass5);
NSLog(@"objectMetaClass - %p %d", objectMetaClass, class_isMetaClass(objectMetaClass));
以上代码所列结论可通过源码查找,字数问题不在阐述,只展示相对应的数据结构既然已经知道三种对象所包含的内容,它们都包含isa指针,那么isa指针有什么作用?
实例对象(instance)的isa指向类对象
当调用对象方法时,通过实例对象(instance)的isa指针找到类对象(class),调用类对象(class)中的对象方法等进行实现
类对象(class)的isa指针指向元类对象(meta-class)
当调用类方法(class)时,通过类对象(class)的isa指针找到元类对象(meta-class),最后找到类方法的实现进行调用
这样就很清晰的了解了代码中常见的方法调用原理
//随手写的 套用以上isa指针原理
//实例化对象
Person *person = [Person alloc] init];
[person test];//对象方法调用
[Person test];//类方法调用
那么如果类存在继承关系是如何调用的呢?
我们从"isa指针图"中可以看出,在class 与 meta-class中存在superClass指针,那么看下图
从图中可以看出来sutdent类继承自Person Person继承自NSObject基类
从继承的角度看,子类可以继承父类的方法,可以直接调用父类的方法,也可以重写父类的方法
那么从指针的角度看呢?
当Student的instance对象要调用Person对象方法时,会先通过isa找到Student的class,然后通过superClass找到Person的class,最后找到对象方法的实现进行调用
可以理解为这样一个过程
isa--->superClass--->superClass-->superClass==nil
如果整个过程都没有找到,会报一个常见的经典错误
unrecognized selector sent to class
到这里是不是感觉可以从isa 指针来明白方法的调用,以及子类继承父类的时候,是怎样的一个调用过程
那配上如下网上经典方法调用图片
结合前面的笔记大概应该明白这幅图怎样的一个调用过程了,对图片做最后一个解释
按照前面说的,meta-class中存在的是类方法,最后找到meta Root Class 类中,依然不存在该类方法,不应该是指针指向nil,而图片却指向class对象呢?
如果Root Class方法中不存在对象方法指向nil
如果存在对象方法,却可以调用成功。
那就违背继承的原理,为什么我调用类方法,没找到却调用对象方法成功了
这是因为OC 是基于C/C++实现的,它并没有严格意义上遵守面向对象的继承关系,因为它在运行时的时候最终会转化成
objc_msgSend([xxx class],@selector(test))
这样的消息传递的方式,它的方法并不在意你是类方法,还是对象方法。
回答开始问题
问题一:对象的isa指针指向哪里?
instance对象的isa指向class对象
class对象的isa指向meta-class对象
meta-class对象的isa指向基类的meta-class对象
问题二:OC的类信息存放在哪里?
对象方法,属性,成员变量,协议信息 存放在class对象中
类方法,存放在meta-class对象中
成员变量的具体值,存放在instance对象中
纯干货,喜欢的话,点赞以示鼓励
下篇文章链接
KVO与KVC原理