欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

浅析IOS中isa指针的作用

程序员文章站 2022-04-12 23:17:52
...

在objective-c语言中,isa指针看名称指的是“是一个”的意思。isa指针是一个指针,具体到代码中,如果是对象,对象中的isa指针是指向的它的类对象。

/// An opaque type that represents an Objective-C class.
typedef struct objc_class *Class;

/// Represents an instance of a class.
struct objc_object {
    Class isa  OBJC_ISA_AVAILABILITY;
};

/// A pointer to an instance of a class.
typedef struct objc_object *id;

如图中所示,任意对象类型都是struct objc_object  *指针的别名。通过观察该结构体变量,发现该结构体中只有一个Class类型的变量,它就是OC对象最基本的一个属性了。那么这个isa指针是用来做什么的呢?通过以上代码,可以发现对象的isa指针类型又是另外一个结构体指针类型struct objc_class *。接下来继续看这个结构体有什么内容:

struct objc_class {
    Class isa  OBJC_ISA_AVAILABILITY;

#if !__OBJC2__
    Class super_class                                        OBJC2_UNAVAILABLE;
    const char *name                                         OBJC2_UNAVAILABLE;
    long version                                             OBJC2_UNAVAILABLE;
    long info                                                OBJC2_UNAVAILABLE;
    long instance_size                                       OBJC2_UNAVAILABLE;
    struct objc_ivar_list *ivars                             OBJC2_UNAVAILABLE;
    struct objc_method_list **methodLists                    OBJC2_UNAVAILABLE;
    struct objc_cache *cache                                 OBJC2_UNAVAILABLE;
    struct objc_protocol_list *protocols                     OBJC2_UNAVAILABLE;
#endif

} OBJC2_UNAVAILABLE;
/* Use `Class` instead of `struct objc_class *` */

从这个结构体中我们可以看出,这个结构体中同样有isa指针,这个指针类型就是这个结构体本身。那么可以大致了解到OC类对象是通过递归的方式来找到它的根类对象的。除了这个isa指针以外,还有其他的一些属性:指向父类对象的指针,名字、版本、描述信息、实例占用内存大小、实例变量列表、方法列表、缓存、遵守的协议列表等。通过这些属性,就可以得到这个类所有的相关信息了。因此,对象的isa指针指向的可以称之为类对象,程序运行时它就指向描述了这个对象所属的具体类型,而不是id这种动态类型。这样对象就可以知道刚才结构体中的所有成员信息了。例如父类是哪个,实例变量有哪些,实例方法有哪些,遵守的协议等。但是这还不够,因为对象还有类方法,类变量可以使用,所以类对象也有个isa指针,它指向的就是它的元类。元类中就包含了类对象创建所需要的所有信息。并且这些信息与对象创建不同的是在编译期就已经确定了。也就是说类对象在程序编译时就确定了。类对象和元类也有相同点,比如他们都有父类指针super_class,元类的父类指针指向的是元类的父亲元类,层层递进,直到指向NSObject这个OC的Root Class(meta)。然后这个根元类的isa指针指向的是它本身,不知道是啥意思。然后用个图来表示就是(自己懒得画了,图是转载来的):

浅析IOS中isa指针的作用

举个例子理解该图:(->表示继承关系)

假设 有继承关系:A->B->C->NSObject,有句代码:

A *a = [A new];
B *b = [B new];
C *c = [C new];
NSObject *root = [NSObject new];

那么a这个实例变量就相当于上图中的Instance of Subclass,b和c就相当于上图中的Instance of Superclass,root就是Instance of Rootclass。它们的super_class指针就是指向的对应的父类对象。

Class aClass = [a class];
Class bClass = [b class];
Class cClass = [c class];
Class rootClass = [root class];

通过实例变量的class方法就可以得到它们的类对象。也就是它们isa指针指向的内容。根据图中继承关系可以表示为:

aClass -> bClass -> cClass -> rootClass

这也就是类对象的super_class指向的内容。

然后要想获得元类就不是通过类对象调用class方法得到了,因为类对象调用class方法得到的是它本身。应该调用的是下面这个方法:

Class aMetaClass = object_getClass(aClass);
Class bMetaClass = object_getClass(bClass);
Class cMetaClass = object_getClass(cClass);
Class rootMetaClass = object_getClass(rootClass);

通过以上这个方法,就可以获取都类对象所对应的元类。前文说到类对象记录了类对象的所有信息,最常用的就是类方法。这个元类就是类对象isa指针指向的内容了。元类之间也有

aMetaClass->bMetaClas->cMetaClass->rootMetaClass这种继承关系存在。

而且,元类isa指针指向的内容就都是相同的了,全都是指向的rootMetaClass。连rootMetaClass它自身isa指针指向的也是它自己。rootMetaClass中定义的就是NSObject类的类方法了,以及NSObject类的内部信息(例如实例方法列表,实例变量列表)。

而NSObject元类就是通过继承NSObject拿到的NSObject的对象信息的。因此,才会有NSObject元类继承自NSObject类这么一条。也说明了在OC中所有的类的根类都是NSObject类。至于NSObject类的父类,那就不存在了。所以是指向的nil。还有NSObject元类的isa指针指向自身,这个可以理解为就是一种面向对象概念——万物皆对象,最终形成一个闭环。

写在最后

通过以上分析,可以了解到isa指针的作用就是描述oc对象的所有信息的。通过这些充足的信息,可以创建出一个结构完整的对象。

 

参考链接:https://www.jianshu.com/p/9e975a1cab93