高效编写代码的方法(十二):类的内省

2016-05-16  本文已影响117人  蜂猴

前言

在之前几篇文章中,我们了解到了一个类的方法是怎么在类中进行存储的;当一个类的实现方法无法找到时,消息转发机制又是如何起作用的。所以,接下来我们要去了解 类 的本身,也就是消息的接收者(receiver)。
在运行时候,我们的程序是怎么知道该像哪一个类去寻找消息的实现呢?

内省

一般来说,如果我们像指定类的实例对象发送消息之后,编译器会检查该类是否有该消息方法的接口,如果没有则会抛出报错或警告。但是对于id这种特殊的类(id可以代表任何一个NSObject),所以编译器会假设id可以对任何消息做出反应而不抛出报错或警告,但在实际运行时可能崩溃。
同时因为objc中类的方法是可以动态进行添加的,所以编译器的检查对于objc来说已经不足够了。

runtime提供了一种类的内省机制,这其中包括了isKindOfClass等我们经常会使用到的方法,这些方法都是NSObject的protocol一部分,所以所有的对象都具有这一套内省方法。

结构

在runtime中,对象以结构构体保存,id类的对象的结构体如下:

typedef struct objc_object {  
    Class isa;  
} *id; 

由此可见,其中包含一个Class类的变量isa,isa指向该对象的类。
所以NSString *str , str中的isa就指向NSString。

Class对象在runtime中也有结构体定义:

typedef struct objc_class *Class;  
struct objc_class {  
    Class isa;  
    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;  
    struct objc_protocol_list *protocols;  
}; 

此结构体的首个变量是isa指针,这说明Class本身也是一个Objective-C对象。结构体里还有个变量叫做super_class,它指向了该类的父类。类对象所属的类型(也就是isa指针所指向的类型)是另外一个类,叫做“元类”(metaclass)。
metaClass是用来描述这个类的数据的一个对象。


类的关系图

isKindOfClass和isMemberOfClass的具体使用就不多说了,两个方法都是通过结构体内的isa指针和super_class指针来确定该类的继承关系。
猜想一下isMemberOfClass可能就是通过isa来判断,而isKindOfClass就主要是通过super_class来实现查找判断。

总结

上一篇下一篇

猜你喜欢

热点阅读