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自己。这样就形成了一个完美的闭环。

相关推荐
张声录11 小时前
【Blackbox Exporter】prober.Handler源码详细分析
ios·iphone·xcode
刘小哈哈哈16 小时前
iOS实现在collectionView顶部插入数据效果
ios·cocoa·xcode
打工人你好1 天前
iOS 逆向学习 - iOS Architecture Core OS Layer
ios
ii_best1 天前
按键精灵ios脚本教程:用函数来实现将图片保存到相册
ios
打工人你好1 天前
iOS 逆向学习 - iOS Security Features:硬件与软件多重防护体系
学习·ios
lichong9511 天前
【Flutter&Dart】页面切换 PageView &PageController(9 /100)
android·flutter·ios·api·postman·postapi·foxapi
打工人你好2 天前
iOS 逆向学习 - iOS Architecture Media Layer
学习·ios
打工人你好2 天前
iOS 逆向学习 - iOS Architecture Cocoa Touch Layer
学习·ios·cocoa
青花瓷2 天前
一个在ios当中采用ObjectC和opencv来显示图片的实例
ios·objective-c·cocoa