OC中isa指针

要认识什么是isa指针,我们得先明确一点:

在Objective-C中,任何类的定义都是对象。类和类的实例(对象)没有任何本质上的区别。任何对象都有isa指针。

那么什么是类呢?在xcode中用快捷键Shift+Cmd+O 打开文件objc.h 能看到类的定义:

可以看到:Class 是一个 objc_class 结构类型的指针, id是一个 objc_object 结构类型的指针

isa指针

isa指针是一个指向对象所属类或元类的指针。它决定了对象可以调用的方法和属性。isa指针在对象的结构中存在,并且在运行时会被自动设置。

在Objective-C中,每个对象都有一个isa指针,它指向该对象所属的类或元类。isa指针决定了对象可以调用的方法和属性。通过isa指针,Objective-C运行时可以在运行时动态地确定对象所属的类,并在该类或其父类中查找对应的方法实现。

下面是一些示例代码来说明isa指针的作用:

@interface MyClass : NSObject
- (void)myMethod;
@end

@implementation MyClass
- (void)myMethod {
    NSLog(@"MyClass's myMethod");
}
@end

int main() {
    MyClass *myObject = [[MyClass alloc] init];
    [myObject myMethod];
    return 0;
}

在上面的示例中,创建了一个名为MyClass的类,它继承自NSObject。MyClass类中定义了一个名为myMethod的方法。

当我们创建一个MyClass对象并调用myMethod方法时,实际上发生了以下过程:

  1. 分配内存并初始化MyClass对象。
  2. 运行时为该对象设置isa指针,使其指向MyClass的类对象。
  3. 在myObject上调用myMethod方法时,运行时首先通过isa指针找到MyClass的类对象。
  4. 运行时在类对象中查找名为myMethod的方法实现并执行。

通过这个过程,我们可以看到isa指针在动态确定对象所属的类的过程中起到了关键作用。它使得我们可以在运行时根据对象的实际类型来调用适当的方法。

每一个对象本质上都是一个类的实例。其中类定义了成员变量和成员方法的列表。对象通过对象的isa指针指向类。
每一个类本质上都是一个对象,类其实是元类(metaClass)的实例。元类定义了类方法的列表。类通过类的isa指针指向元类。
所有的元类最终继承一个根元类,根元类isa指针指向本身,形成一个封闭的内循环。

每个实例对象有个isa的指针,他指向对象的类,而Class里也有个isa的指针, 指向metaClass(元类)。元类保存了类方法的列表。当类方法被调用时,先会从本身查找类方法的实现,如果没有,元类会向他父类查找该方法。同时注意的是: 元类(metaClass)也是类,它也是对象。元类也有isa指针,它的isa指针最终指向的是一个根元类(root metaClass).根元类的isa指针指向本身,这样形成了一个封闭的内循环。

实例如下:

@interface Dog : NSObject{
    NSInteger _age;
    NSString *name;
}
 
- (void)pengta;
+ (void)hehe;
 
@end
 
@implementation Dog
 
- (void)pengta{
    printf("instance dog");
}
+ (void)hehe{
    printf("class dog");
}
 
@end

所有Dog的实例的isa都指向了Dog(Class)。

Dog(Class)是一个全局变量,其中记录了类名、成员变量信息、property信息、protocol信息和实例方法列表等。

Dog(Class)的isa指向了全局变量Dog(meta-class),meta-class里只记录了类名、类方法列表等。

Dog *dog = [[Dog alloc] init];
[dog pengta];

向Dog (instance) 发送消息pengta时,运行时会通过isa指针查找到Dog(Class),这里保存着本类中定义的实例方法的指针。

[Dog hehe];

向Dog(Class)发送消息hehe时,运行时会通过isa查找到Dog(meta-class),这里保存着本类中定义的类方法的指针。

Meta Class(元类)

所有的类自身也是一个对象,我们可以向这个对象发送消息(即调用类方法)。如:

NSArray *array = [NSArray array];

这个例子中,+array消息发送给了NSArray类,而这个NSArray也是一个对象。既然是对象,那么它也是一个objc_object指针,它包含一个指向其类的一个isa指针,这个isa指针也要指向这个类所属的类。那么这些就有一个问题了,这个isa指针指向什么呢?这就引出了meta-class的概念:

meta-class是一个类对象的类

当我们向一个对象发送消息时,runtime会在这个对象所属的这个类的方法列表中查找方法;而向一个类发送消息时,会在这个类的meta-class的方法列表中查找。

meta-class 是必须的,因为它为一个 Class 存储类方法。每个Class都必须有一个唯一的 meta-class,因为每个Class的类方法基本不可能完全相同。

再深入一下,meta-class也是一个类,也可以向它发送一个消息,那么它的isa又是指向什么呢?为了不让这种结构无限延伸下去,Objective-C的设计者让所有的meta-class的isa指向基类的meta-class,以此作为它们的所属类。即,任何NSObject继承体系下的meta-class都使用NSObject的meta-class作为自己的所属类 (在一定程度上可以理解为若一个Class继承自NSObject,则这个Class的meta-class继承自NSObject的meta-class),而基类的meta-class的isa指针是指向它自己,这就是说 NSObject 的 meta-class 的 isa 指针指向NSObject 的 meta-class自己。这样就形成了一个完美的闭环。

相关推荐
志飞28 分钟前
ios通过xib创建控件
objective-c·xib的使用·xib创建控件
ClaNNEd@7 小时前
在macOS上构建Flutter iOS应用
flutter·macos·ios
王中王程序猿28 小时前
记使用AScript自动化操作ios苹果手机
python·ios·自动化
ssslar12 小时前
Flutter PIP 插件 ---- iOS Video Call
flutter·ios·pip
流年诠释一切17 小时前
golang 版 E签宝请求签名鉴权方式
开发语言·ios·golang
2501_9044477418 小时前
曝苹果2026年秋季推首款折叠iPhone
智能手机·django·objective-c·pygame·tornado
安和昂1 天前
effective—Objective—C 第七章阅读笔记
笔记·objective-c
神仙别闹1 天前
基于IOS开发五子棋游戏
游戏·ios
gp1031 天前
iOS主要知识点梳理回顾-5-运行时方法交换
ios·方法交换
gp1031 天前
iOS主要知识点梳理回顾-3-运行时消息机制
ios·运行时