zl程序教程

您现在的位置是:首页 >  移动开发

当前栏目

iOS - isa、superclass指针,元类superclass指向基类本身(上)

ios 指针 指向 基类 本身
2023-09-27 14:25:58 时间
一. 对象

instance对象,也称实例对象


class对象,也称类对象


meta-calss对象 也称元类对象


本文将探讨如下问题


这些对象中包含了什么信息


这些信息如何关联


成员变量是存在哪里的


类方法与实例方法是存在哪里的


如何找到superclass


instance对象


1. 什么是instance对象


通过 alloc之后的都是instance对象.这里还需要强调的是 instance对象不仅仅是NSObject对象,还有一个代理类NSProxy 也能创建instance对象

// 创建一个对象

NSObject* obj [NSObject alloc];


Class对象


1. 获取class对象


创建一个继承自NSObject的ClassObject类

- (void)viewDidLoad {

 [super viewDidLoad];

 ClassObject *clsObj [[ClassObject alloc] init];

 [self fetchClassWithClassObject:clsObj];

//获取class的所有方法

- (void)fetchClassWithClassObject:(ClassObject *)clsObj {

 Class objClass1 [clsObj class];

 Class objClass2 [ClassObject class];

 Class objClass3 object_getClass(clsObj);

 NSLog( \n objClass1 % \n objClass2 % \n objClass3 % \n ,NSStringFromClass(objClass1), NSStringFromClass(objClass2), NSStringFromClass(objClass3) );

 NSLog( \n\n objClass1 %p \n objClass2 %p \n objClass3 %p , objClass1, objClass2, objClass3);

//打印结果

2021-05-04 10:34:36.333929 0800 ClassDemo[26079:8911440] 

 objClass1 ClassObject 

 objClass2 ClassObject 

 objClass3 ClassObject

2021-05-04 10:34:36.334052 0800 ClassDemo[26079:8911440] 

 objClass1 0x109a61548 

 objClass2 0x109a61548 

 objClass3 0x109a61548


打印可见 不管用什么方式获取的class对象都是一样的 打印地址也一致 说明在项目中一个Class仅有一个对象 但是上面三种获取class的方式有什么不同呢


前两种是通过方法获取的 直接获取的是当前instance的Class 但是第三种方式不一样 这种方式获取的是当前instance的isa的值


可以这样做个实验 给clsObj添加一个kvo

[clsObj addObserver:self forKeyPath: class options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];


打印结果变为

2021-05-04 10:54:32.415419 0800 ClassDemo[28990:8934226] 

 objClass1 ClassObject 

 objClass2 ClassObject 

 objClass3 NSKVONotifying_ClassObject

2021-05-04 10:54:32.415562 0800 ClassDemo[28990:8934226] 

 objClass1 0x10fea3550 

 objClass2 0x10fea3550 

 objClass3 0x600001300240


第三个值变成了NSKVONotifying_ClassObject


2. class对象中的信息


isa


superclass


属性 property


instance 方法


协议 protocal


成员变量 这里的成员变量信息并不是一个 instance 中成员变量的值 而是指在这个 Class 中有哪些成员变量 是 NSSting 的 还是 int 类型的


其它


meta-class 对象


1. 获取meta-class对象


在开发中是不会手动去 alloc一个元类对象 可以通过object_getClass函数获取class的isa类取之 代码如下

- (void)fetchMetaClassWithClassObject:(ClassObject *)clsObj {

 //1. 获取一个对象的isa

 Class objIsa object_getClass(clsObj);

 //获取元类对象

 Class metaClass object_getClass(objIsa);

 NSLog( \n metaClass %p \n metaClass % , metaClass, NSStringFromClass(metaClass));

}


会发现 元类还是当前的Class 但是是另一个对象地址


其次 不管是class对象还是元类对象 其类型都是Class 说明在内存结构上是一致的 但是其包含的信息含义是不一样的 其用途也不一样


meta-class 对象中的信息


isa


superclass


类方法信息


其它


对象总结


总共有三种对象 instance对象、class对象 meta-class对象成员变量的值都存在instance中属性、instance 实例 方法、协议protocol都存于class中类方法都存于meta-class中


image.png

image


二. isa

以上的三种对象是如何关联起来的呢 是通过isa关联的:


instance对象的isa的值是class对象 class对象的isa的值是meta-calss对象


既然实例方法是存在于class对象中 那么当给一个instance对象发送消息的时候 是如何找到具体的实现方法的呢


当调用实例方法的时候 通过instance对象中的isa找到class 找到对应的实例方法的实现


同理 类方法的调用也是一样的


当调用类方法时 通过class对象的isa指针找到meta-class 并找到对应的类方法实现