// Property 'name' requires method 'name' to be defined - use @dynamic or provide a method implementation in this category // Property 'name' requires method 'setName:' to be defined - use @dynamic or provide a method implementation in this category
/// An opaque type that represents an Objective-C class. typedefstruct objc_class *Class;
/// Represents an instance of a class. struct objc_object { Class _Nonnull isa OBJC_ISA_AVAILABILITY; };
/// A pointer to an instance of a class. typedefstruct objc_object *id;
可以看出 id 是 objc_object 结构体类型的指针,objc_object 包含了一个 Class 类型的变量 isa ,Class 是 objc_class 类型的指针。 再看看 NSObject.h 中的定义
1 2 3 4 5 6 7 8
// NSObject.h
@interfaceNSObject <NSObject> { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wobjc-interface-ivars" Class isa OBJC_ISA_AVAILABILITY; #pragma clang diagnostic pop }
这里面包含了一个 Class 类型的变量 isa 。这个 Class 也就是 objc_class 类型的指针。 事实上每个实例变量都会包含一个 objc_object 结构体,该结构体的第一个成员变量就是 isa 指针。既然是指针,那么 objc_class 也是一个对象,我们称之为“类对象”,这个类对象是一个单例,程序运行中只存在一份。
再看看 runtime.h 是怎么定义 objc_class 结构体的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
// runtime.h
struct objc_class { Class _Nonnull isa OBJC_ISA_AVAILABILITY;
#if !__OBJC2__ Class _Nullable super_class OBJC2_UNAVAILABLE; constchar * _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 指针。它指向的是类的元类(metaclass)。objc_class 负责保存类的实例变量、方法列表、缓存方法列表、协议列表等。元类(metaclass)则负责保存类方法列表。
继承体系图
每一个实例对象都有一个 isa 指针指向其类对象,用来表明其类型,类对象也有一个 isa 指针,指向其元类,元类同样存在一个 isa 指针,指向其根元类,根元类的 isa 指针则指向自身。这些类对象则构成了类的继承体系。