入门
在 Objective-C 中,objc_object
和 objc_class
是运行时系统的核心结构,用于表示对象和类。理解它们的结构和关系对于掌握 Objective-C 的运行时机制非常重要。
objc_object
结构
objc_object
结构代表一个 Objective-C 对象。每个 Objective-C 对象都有一个 isa
指针,指向它的类对象。
objc_object
结构示例
struct objc_object {
Class isa; // isa 指针,指向类对象
};
isa
:这是一个指向类对象的指针,通过它可以找到对象所属的类及其方法和其他元数据。
objc_class
结构
objc_class
结构代表一个类对象。类对象本质上也是对象,因此它也有一个 isa
指针,指向它的元类(meta-class)。此外,objc_class
结构还包含了有关类的其他信息,如方法列表、成员变量、协议等。
objc_class
结构示例
struct objc_class {
Class isa; // 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; // 协议列表
};
objc_class
结构字段解释
isa
:指向元类对象的指针。元类对象包含类方法和元类的元数据。super_class
:指向父类对象的指针。实现继承链。name
:类的名称。version
:类的版本信息。info
:类的信息标志位,包含一些布尔值标志。instance_size
:实例的大小,表示分配对象内存时需要的大小。ivars
:成员变量列表,指向类的成员变量列表。methodLists
:方法列表数组,指向类的方法列表。cache
:方法缓存,指向方法调用的缓存。protocols
:协议列表,指向类实现的协议列表。
objc_class
和 objc_object
的关系
在 Objective-C 中,类本身也是对象。这意味着 objc_class
结构是 objc_object
结构的一个子类。每个类对象都有一个 isa
指针,指向其元类对象。元类对象也有一个 isa
指针,指向根元类对象。
类和元类关系图
+--------------------+ +--------------------+ +--------------------+
| 实例对象 | --> | 类对象 | --> | 元类对象 |
+--------------------+ +--------------------+ +--------------------+
| isa -> Class | | isa -> MetaClass | | isa -> RootMetaClass|
+--------------------+ +--------------------+ +--------------------+
| | | super_class | | super_class |
+--------------------+ +--------------------+ +--------------------+
- 实例对象 的
isa
指针指向类对象。 - 类对象 的
isa
指针指向元类对象。 - 元类对象 的
isa
指针指向根元类对象。
具体示例
以下是一个具体示例,展示如何使用 objc_object
和 objc_class
结构:
#import <objc/runtime.h>
#import <Foundation/Foundation.h>
@interface MyClass : NSObject
@end
@implementation MyClass
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
MyClass *obj = [[MyClass alloc] init];
Class objClass = object_getClass(obj);
Class objMetaClass = object_getClass(objClass);
NSLog(@"Instance: %p", obj);
NSLog(@"Class: %p", objClass);
NSLog(@"MetaClass: %p", objMetaClass);
NSLog(@"Instance isa: %p", *(uintptr_t *)obj);
NSLog(@"Class isa: %p", *(uintptr_t *)objClass);
NSLog(@"MetaClass isa: %p", *(uintptr_t *)objMetaClass);
}
return 0;
}
在这个示例中,我们使用 object_getClass
函数获取对象的类和元类,然后打印它们的内存地址和 isa
指针。输出结果显示了对象、类和元类之间的关系。
小结
objc_object
:表示一个 Objective-C 对象,包含一个isa
指针,指向类对象。objc_class
:表示一个类对象,包含isa
指针、父类指针、方法列表、成员变量等信息。- 类和元类:类对象也是对象,
isa
指针指向元类对象,元类对象的isa
指针指向根元类对象。
理解 objc_object
和 objc_class
的结构及其关系,有助于深入掌握 Objective-C 的运行时机制和面向对象编程模型。
拓展
objc_object 结构代表一个 Objective-C 对象,objc_class 结构代表一个类对象,那么什么结构代表元类对象 ?什么结构代表根元类对象 ?
在 Objective-C 中,类对象和元类对象实际上使用相同的结构体,即 objc_class
结构体。元类对象是特殊的类对象,用于存储类方法。当一个类对象调用类方法时,这个调用实际上是通过它的元类对象实现的。
类对象、元类对象和根元类对象
- 类对象:用于存储实例方法和实例变量。
- 元类对象:用于存储类方法。每个类对象都有一个对应的元类对象。
- 根元类对象:所有元类的终极元类,通常是
NSObject
的元类。
objc_class
结构体
objc_class
结构体同时表示类对象和元类对象。以下是 objc_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
指针,指向其元类对象。 - 元类对象的
isa
指针指向根元类对象。 - 根元类对象 (通常是 NSObject 的元类) 的
isa
指针指向自己,这构成了一个循环,表示类对象体系的终点。
元类对象和根元类对象的关系图
+-------------------+ +-------------------+ +-------------------+
| 实例对象 | --> | 类对象 | --> | 元类对象 |
+-------------------+ +-------------------+ +-------------------+
| isa -> Class | | isa -> MetaClass | | isa -> RootMetaClass|
+-------------------+ +-------------------+ +-------------------+
| | | super_class | | super_class |
+-------------------+ +-------------------+ +-------------------+
具体的例子
假设我们有一个类 MyClass
,它继承自 NSObject
,我们可以构造以下关系:
@interface MyClass : NSObject
@end
@implementation MyClass
@end
在内存中的关系可以表示为:
MyClass instance -> MyClass -> MyClass's MetaClass -> NSObject's MetaClass -> NSObject's MetaClass (itself)
代码示例
下面的代码展示了如何获取和打印类对象和元类对象的信息:
#import <objc/runtime.h>
#import <Foundation/Foundation.h>
@interface MyClass : NSObject
@end
@implementation MyClass
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
MyClass *obj = [[MyClass alloc] init];
Class objClass = object_getClass(obj); // 获取类对象
Class objMetaClass = object_getClass(objClass); // 获取元类对象
Class rootMetaClass = object_getClass(objMetaClass); // 获取根元类对象
NSLog(@"Instance: %p", obj);
NSLog(@"Class: %p", objClass);
NSLog(@"MetaClass: %p", objMetaClass);
NSLog(@"RootMetaClass: %p", rootMetaClass);
NSLog(@"Instance isa: %p", *(uintptr_t *)obj);
NSLog(@"Class isa: %p", *(uintptr_t *)objClass);
NSLog(@"MetaClass isa: %p", *(uintptr_t *)objMetaClass);
NSLog(@"RootMetaClass isa: %p", *(uintptr_t *)rootMetaClass);
}
return 0;
}
输出结果
运行上面的代码,输出结果可能如下:
Instance: 0x600003b7a0c0
Class: 0x10f512340
MetaClass: 0x10f512370
RootMetaClass: 0x10f512370
Instance isa: 0x10f512340
Class isa: 0x10f512370
MetaClass isa: 0x10f512370
RootMetaClass isa: 0x10f512370
在这个示例中,我们看到:
- 实例对象的
isa
指针指向类对象。 - 类对象的
isa
指针指向元类对象。 - 元类对象的
isa
指针指向根元类对象。 - 根元类对象的
isa
指针指向自己。
总结
objc_object
:表示一个实例对象,包含一个isa
指针,指向类对象。objc_class
:表示一个类对象,包含isa
指针、父类指针、方法列表等信息。类对象和元类对象使用相同的结构体。- 元类对象:也是
objc_class
结构体,isa
指针指向根元类对象。 - 根元类对象:
isa
指针指向自己,终结了类对象体系的循环。
理解这些结构和关系对于掌握 Objective-C 运行时的动态特性和面向对象编程模型非常重要。