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

简介: 本文已同步至掘金:iOS - isa、superclass指针,元类superclass指向基类本身

一. 对象


instance对象,也称实例对象


class对象,也称类对象


meta-calss对象,也称元类对象


本文将探讨如下问题:


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


  • 这些信息如何关联


  • 成员变量是存在哪里的


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


  • 如何找到superclass


instance对象


1. 什么是instance对象


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

// 创建一个对象
NSObject* obj = [NSObject alloc];


Class对象


1. 获取class对象


创建一个继承自NSObjectClassObject

- (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对象中的信息


  1. isa


  1. superclass


  1. 属性 property


  1. instance 方法


  1. 协议 protocal


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


  1. 其它


meta-class 对象


1. 获取meta-class对象


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

- (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 对象中的信息


  1. isa


  1. superclass


  1. 类方法信息


  1. 其它


对象总结


  • 总共有三种对象: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, 并找到对应的类方法实现


相关文章
|
存储 C++
04-深入了解isa指针以及内部结构
04-深入了解isa指针以及内部结构
78 0
04-深入了解isa指针以及内部结构
|
存储
03-isa指针 & superclass指针
03-isa指针 & superclass指针
63 0
|
存储 Unix 编译器
|
存储 监控 Unix
iOS-底层原理36:内存优化(一) 野指针探测
iOS-底层原理36:内存优化(一) 野指针探测
645 0
iOS-底层原理36:内存优化(一) 野指针探测
|
编译器 iOS开发
iOS逆向 03:循环选择指针(下)
iOS逆向 03:循环选择指针(下)
129 0
iOS逆向 03:循环选择指针(下)
|
存储 iOS开发 MacOS
iOS逆向 03:循环选择指针(上)
iOS逆向 03:循环选择指针(上)
78 0
iOS逆向 03:循环选择指针(上)
|
存储 C++
iOS-底层原理 09:类 & isa 经典面试题分析
iOS-底层原理 09:类 & isa 经典面试题分析
165 0
iOS-底层原理 09:类 & isa 经典面试题分析
|
存储 设计模式 编译器
iOS-底层原理 07:isa与类关联的原理
iOS-底层原理 07:isa与类关联的原理
126 0
iOS-底层原理 07:isa与类关联的原理