在创建一个对象的时候,我们有时会用id来表示,系统会在运行时找到对象实际所属的类,这是怎么实现的呢?id又是什么?
/// A pointer to an instance of a class.
typedef struct objc_object *id;
/// Represents an instance of a class.
struct objc_object {
Class _Nonnull isa OBJC_ISA_AVAILABILITY;
};
可以看到,id实际是一个结构体指针,这个结构体中包含一个isa成员,类型为Class。
每个对象都最终都继承于NSObject,通过点击NSObject,可以发现如下:
@interface NSObject <NSObject> {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-interface-ivars"
Class isa OBJC_ISA_AVAILABILITY;
#pragma clang diagnostic pop
}
有一个isa成员变量,其类型是Class类型。
创建一个对象,就是对一个类进行实例化,因此需要知道类的模板,根据这个模板来创建实例对象,因此这个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;
/* Use `Class` instead of `struct objc_class *` */
注意,这个结构体中也有一个是isa指针,因此可以判断Class其实也是一个对象,叫做类对象,也就是说,在创建类的实例对象的时候,实例对象的isa会指向对象所属类的类对象,这个类对象中包含创建实例所需的基本信息,包含方法列表,属性列表,协议列表等。
那么,类对象中的isa指向的是哪里?
可以看到,类对象中包含的是创建该类的实例对象所需的基本信息,并没包含创建类对象所需的信息,因此,类对象中的isa实际指向的是描述这个类对象的类,称为元类
元类中包含这个类对象的基本信息,类方法列表等信息。
元类中也有isa指针,元类中的isa指针指向根类。
网友评论