返回

从类的结构分析理解isa指针的指向(上)

IOS

前言

在Objective-C中,每个对象都有一个isa指针,这个指针指向该对象的类。isa指针是一个非常重要的概念,它可以帮助我们理解Objective-C中对象的内存布局,以及OOP的一些基本概念。

类的结构

在Objective-C中,类是一个数据结构,它包含了该类的一些信息,比如:

  • 类名
  • 父类
  • 实例变量
  • 方法

类在内存中是以一种特定的方式组织的,这种组织方式称为类的内存布局。类的内存布局如下图所示:

类结构:
+-------------------------------------+
| 实例变量区                          |
+-------------------------------------+
| 方法区                              |
+-------------------------------------+
| 类变量区                          |
+-------------------------------------+
| 元类指针                          |
+-------------------------------------+
| 父类指针                          |
+-------------------------------------+
| 类名                                |
+-------------------------------------+

其中:

  • 实例变量区:存储该类的实例变量。
  • 方法区:存储该类的方法。
  • 类变量区:存储该类的类变量。
  • 元类指针:指向该类的元类。
  • 父类指针:指向该类的父类。
  • 类名:该类的名称。

isa指针

isa指针指向该对象的类。在内存中,isa指针位于对象的实例变量区的最前面。如下图所示:

对象内存布局:
+-------------------------------------+
| isa指针                              |
+-------------------------------------+
| 实例变量区                          |
+-------------------------------------+

isa指针的指向

我们有一个对象LGPerson,继承与NSObject。我们来打印一下它的isa指针:

#import <objc/runtime.h>

int main() {
    LGPerson *person = [[LGPerson alloc] init];
    NSLog(@"%@", [NSString stringWithFormat:@"%p", object_getClass(person)]);
    return 0;
}

输出结果:

0x100008c98

从输出结果可以看出,isa指针指向的是该对象的类。在本文中,isa指针指向的是LGPerson类。

我们可以继续追溯isa指针的指向,直到根元类。根元类是所有类的父类,它的isa指针指向它自己。如下图所示:

isa指针的指向:
+-------------------------------------+
| isa指针                              |
+-------------------------------------+
| 类                                  |
+-------------------------------------+
| ...                                  |
+-------------------------------------+
| 元类                                |
+-------------------------------------+
| ...                                  |
+-------------------------------------+
| 根元类                              |
+-------------------------------------+
| isa指针                              |
+-------------------------------------+
| 根元类                              |
+-------------------------------------+

通过上面的分析,我们可以得出以下结论:

  • isa指针指向该对象的类。
  • isa指针可以帮助我们追溯对象的类继承关系。
  • 根元类的isa指针指向它自己。

isa指针的疑问

在上面的分析中,我们提到isa指针指向该对象的类。但是,我们是如何知道isa指针指向的是哪个类的呢?

其实,isa指针指向的类是通过编译器生成的。编译器会在每个类的开头生成一个指向该类的指针,这个指针就是isa指针。如下图所示:

类结构:
+-------------------------------------+
| 实例变量区                          |
+-------------------------------------+
| 方法区                              |
+-------------------------------------+
| 类变量区                          |
+-------------------------------------+
| 元类指针                          |
+-------------------------------------+
| 父类指针                          |
+-------------------------------------+
| 类名                                |
+-------------------------------------+
| isa指针                              |
+-------------------------------------+

编译器会在LGPerson类的开头生成一个指向LGPerson类的指针,这个指针就是LGPerson对象的isa指针。

结语

本文从类的结构分析的角度,来理解isa指针的指向。我们了解了isa指针的指向,以及如何通过isa指针追溯对象的类继承关系。我们还了解了isa指针是如何生成的。

在下一篇文章中,我们将继续分析isa指针,并了解isa指针在Objective-C中的其他应用。