19.从NSObject了解isa指针

2017-07-05  本文已影响0人  小笨憨

如果你曾经对ObjC底层的实现有一定的了解,你应该会知道Objective-C对象都是 C 语言结构体,所有的对象都包含一个类型为 isa 的指针,那么你可能确实对 ObjC 的底层有所知,不过现在的 ObjC 对象的结构已经不是这样了。代替 isa 指针的是结构体 isa_t,这个结构体中“包含”了当前对象指向的类的信息,这篇文章中会介绍一些关于这个变化的知识。

struct objc_object {
    isa_t isa;
};

当 ObjC 为一个对象分配 内存,初始化实例变量后,在这些对象的实例变量的结构体中的第一个就是 isa。

所有继承自 NSObject 的类实例化后的对象都会包含一个类型 isa_t 的结构体。

从上图中可以看出,不只是实例会包含一个 isa 结构体,所有的类也有这么一个 isa。在 ObjC 中 Class 的定义也是一个名为 objc_class 的结构体,如下:

struct objc_class : objc_object {
    isa_t isa;
    Class superclass;
    cache_t cache;
    class_data_bits_t bits;
};
由于 objc_class 结构体是继承自 objc_object 的,所以在这里显式地写出了 isa_t isa 这个成员变量。

isa 指针的作用与元类

到这里,我们就明白了:Objective-C 中类也是一个对象。

这个 isa 包含了什么呢?回答这个问题之前,要引入了另一个概念 元类(meta class),我们先了解一些元类的信息。

因为在 Objective-C 中,对象的方法并没有存储于对象的结构体中(如果每一个对象都保存了自己能执行的方法,那么对内存的占用有极大的影响)。

当实例方法被调用时,它要通过自己持有的 isa 来查找对应的类,然后在这里的 class_data_bits_t 结构体中查找对应方法的实现。同时,每一个 objc_class 也有一个指向自己的父类的指针 super_class 用来查找继承的方法。

关于如何在 class_data_bits_t 中查找对应方法会在之后的文章中讲到。这里只需要知道,它会在这个结构体中查找到对应方法的实现就可以了。
struct objc_class {
    Class isa  OBJC_ISA_AVAILABILITY;    

#if !__OBJC2__
    Class super_class                                                                
    const char *name                                   
    long version                                               
    long info                                                    
    long instance_size                                      
    struct objc_ivar_list *ivars                          
    struct objc_method_list **methodLists    // 方法定义的链表
    struct objc_cache *cache                          // 方法缓存,对象接到一个消息会根据isa指针查找消息对象
    struct objc_protocol_list *protocols          // 协议链表                 
#endif

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

super_class:父类,如果该类已经是最顶层的根类,那么它为NULL。

version:类的版本信息,默认为0

info:供运行期使用的一些位标识。

instance_size:该类的实例变量大小

ivars:成员变量的数组

每一个对象本质上都是一个类的实例。其中类定义了成员变量和成员方法的列表。对象通过对象的isa指针指向类。

每一个类本质上都是一个对象,类其实是元类(meteClass)的实例。元类定义了类方法的列表。类通过类的isa指针指向元类。

所有的元类最终继承一个根元类,根元类isa指针指向本身,形成一个封闭的内循环。

上一篇 下一篇

猜你喜欢

热点阅读