OC 中有 3种对象,分别是 实例对象instance、类对象class object、元类对象metaclass
instance对象实例
我们经常使用id来声明一个对象,那id的本质又是什么呢?打开#import<objc/objc.h>文件,可以发现以下几行代码
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结构体,而我们常用的id也就是这个结构体的指针。
这个结构体只有一个成员变量,这是一个Class类型的变量isa,也是一个结构体指针,那这个指针又指向什么呢?
答案是:面向对象中每一个对象都必须依赖一个类来创建,因此对象的isa指针就指向对象所属的类。
class object(类对象)/metaclass(元类)
继续查看结构体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 *` */
struct objc_classs结构体里存放的数据称为元数据(metadata),通过成员变量的名称我们可以猜测里面存放有指向父类的指针、类的名字、版本、实例大小、实例变量列表、方法列表、缓存、遵守的协议列表等,这些信息就足够创建一个实例了,该结构体的第一个成员变量也是isa指针,这就说明了Class本身其实也是一个对象,我们称之为类对象。
放一张大神的图,我们可以清楚的看到,实例对象的isa 指向类对象,类对象的isa 指向元类对象。而元类对象的isa都指向根元类。也就是 NSObject 元类。
如果我们想获取isa指针的指向对象要怎么获得
OBJC_EXPORT BOOL class_isMetaClass(Class cls)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0);
OBJC_EXPORT Class object_getClass(id obj)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0);
class_isMetaClass用于判断Class对象是否为元类,object_getClass用于获取对象的isa指针指向的对象。