返回

揭秘iOS isa——深入剖析类、对象、isa之间的底层结构

IOS

前言

在上一篇文章中,我们对对象的底层本质和isa的原理进行了分析,发现对象里的isa成员变量很特别。在本文中,我们将从isa入手,继续探索类、对象和isa之间的底层结构。

首先,我们来看两个类,分别是XJPerson(继承自NSObject)和XJStudent(继承自XJPerson)。这两个类在内存中的布局如下图所示:

XJPerson:
+-------+       +-------+       +-------+
| isa    |  ->   | isa    |  ->   | isa    |
+-------+       +-------+       +-------+
| name   |       | name   |       | name   |
+-------+       +-------+       +-------+
| age    |       | age    |       | age    |
+-------+       +-------+       +-------+
| gender |       | gender |       | gender |
+-------+       +-------+       +-------+

XJStudent:
+-------+       +-------+       +-------+
| isa    |  ->   | isa    |  ->   | isa    |
+-------+       +-------+       +-------+
| name   |       | name   |       | name   |
+-------+       +-------+       +-------+
| age    |       | age    |       | age    |
+-------+       +-------+       +-------+
| gender |       | gender |       | gender |
+-------+       +-------+       +-------+
| score  |       | score  |       | score  |
+-------+       +-------+       +-------+

从上图可以看出,XJPerson和XJStudent对象在内存中的布局是一致的,都包含了isa、name、age和gender这四个成员变量。其中,isa成员变量指向了该对象的类对象(XJPerson或XJStudent),而其他成员变量则存储了该对象特有的数据。

isa指针

isa指针是对象的一个成员变量,它指向了该对象的类对象。类对象也是一个对象,它存储了该类相关的信息,比如类名、成员变量列表、方法列表等。

isa指针在Objective-C和Swift中都有着重要的作用。在Objective-C中,isa指针用于确定对象的类型,并根据对象的类型调用相应的方法。在Swift中,isa指针用于确定对象的类型,并根据对象的类型进行类型检查。

类、对象和isa之间的关系

类、对象和isa之间的关系可以用以下三点来概括:

  1. 类是对象的模板,对象是类的实例。
  2. isa指针指向对象的类对象。
  3. 类对象存储了该类相关的信息,比如类名、成员变量列表、方法列表等。

这三点关系构成了类、对象和isa之间的基本结构。

内存布局

类、对象和isa在内存中的布局如下图所示:

+-------+       +-------+       +-------+
| isa    |  ->   | isa    |  ->   | isa    |
+-------+       +-------+       +-------+
| name   |       | name   |       | name   |
+-------+       +-------+       +-------+
| age    |       | age    |       | age    |
+-------+       +-------+       +-------+
| gender |       | gender |       | gender |
+-------+       +-------+       +-------+

XJPerson:
+-------+       +-------+       +-------+
| isa    |  ->   | isa    |  ->   | isa    |
+-------+       +-------+       +-------+
| name   |       | name   |       | name   |
+-------+       +-------+       +-------+
| age    |       | age    |       | age    |
+-------+       +-------+       +-------+
| gender |       | gender |       | gender |
+-------+       +-------+       +-------+
| score  |       | score  |       | score  |
+-------+       +-------+       +-------+

XJStudent:

从上图可以看出,XJPerson和XJStudent对象在内存中的布局是一致的,都包含了isa、name、age和gender这四个成员变量。其中,isa成员变量指向了该对象的类对象(XJPerson或XJStudent),而其他成员变量则存储了该对象特有的数据。

运行时机制

运行时机制是iOS中非常重要的一个机制,它允许程序在运行时动态地加载、链接和执行代码。运行时机制的实现依赖于isa指针。

当程序运行时,系统会根据对象的isa指针找到该对象的类对象,然后根据类对象中的信息来确定对象的类型,并调用相应的方法。

运行时机制的应用非常广泛,比如动态加载库、动态类型检查、反射等。

示例

下面我们通过一个示例来说明isa指针的作用。

我们创建一个XJPerson对象和一个XJStudent对象,然后调用这两个对象的name属性。

XJPerson *person = [[XJPerson alloc] init];
person.name = @"张三";

XJStudent *student = [[XJStudent alloc] init];
student.name = @"李四";

NSLog(@"person.name = %@", person.name);
NSLog(@"student.name = %@", student.name);

输出结果为:

person.name = 张三
student.name = 李四

从输出结果可以看出,person.name和student.name的值分别为“张三”和“李四”。这是因为person对象和student对象的isa指针指向了不同的类对象,从而导致了不同的方法调用。

结语

本文深入探讨了iOS中的isa指针,剖析了类、对象和isa之间的底层结构,揭示了内存布局和运行时机制,并提供了清晰的示例和代码片段,帮助读者理解Objective-C和Swift中的内存管理和运行时机制。