runtime的核心是消息传递,介绍消息传递都会讲到对象、类、isa指针这些概念,来表述消息是如何转发的。本文直接从objc_object和objc_class结构体入手,介绍以上概念。供自己学习记录并为同样迷惑的人儿解一丢丢惑。
objc_object
objc_object就是OC中对象object的c语言定义,可以看到对象就是一个结构体
/// Represents an instance of a class.
struct objc_object {
Class _Nonnull isa OBJC_ISA_AVAILABILITY;
};
/// A pointer to an instance of a class.
typedef struct objc_object *id;
此结构体内有一个isa成员变量,其类型为Class,那么Class是什么类型?我们下一小节介绍。先看一下在OC中常用的一个通用类型id,最初写代码的时候有没有疑惑过为什么声明id类型的变量不用加上*,因为它本身就是一个指针,是一个指向objc_object的指针。
objc_class
Class类型其实就是指向objc_class结构体的指针,objc_class结构体里存储了父类、方法列表等信息:
/// An opaque type that represents an Objective-C class.
typedef struct objc_class *Class;
struct objc_class {
Class _Nonnull isa OBJC_ISA_AVAILABILITY;
#if !__OBJC2__
Class _Nullable super_class OBJC2_UNAVAILABLE;
const char * _Nonnull name OBJC2_UNAVAILABLE;
long version OBJC2_UNAVAILABLE;
long info OBJC2_UNAVAILABLE;
long instance_size OBJC2_UNAVAILABLE;
struct objc_ivar_list * _Nullable ivars OBJC2_UNAVAILABLE;
struct objc_method_list * _Nullable * _Nullable methodLists OBJC2_UNAVAILABLE;
struct objc_cache * _Nonnull cache OBJC2_UNAVAILABLE;
struct objc_protocol_list * _Nullable protocols OBJC2_UNAVAILABLE;
#endif
} OBJC2_UNAVAILABLE;
实例对象、类对象、元类
objc_class结构里也有isa指针,可以发现其实类也是一种对象,那什么是类对象。直接看代码,p就是实例对象,p1、p2都是类对象
Person *p = [[Person alloc] init];
Class p1 = [p class];
Class p2 = [Person class];
p1是通过实例对象获取到其类对象,p2是通过类名,类名作为消息的接收者时代表的是类对象,类对象获取Class得到的是其本身。
实例对象(objc_object)结构体中isa指针指向的是类对象(objc_class)结构体,类对象中保存的是创建实例对象、方法的一些信息。类对象(objc_class)中的isa则是指向一个叫做元类(meta-class)的(objc_class)结构体,元类中存储这创建类对象和类方法的信息。那么元类中还有isa指针,又指向哪?我们放出经典图(Runtime 工程师 Greg Parker 在他的博客贴出的图表)
Objective-C 的创建者让所有元类的isa指针指向根元类,根元类的isa指针指向自身。
至此,应该可以清楚的理解实例对象、类、元类的关系了叭!(以上若有理解错误或描述错误欢迎各位大佬赐教~)
网友评论