objc_object 与 objc_class 是一定要了解的底层结构

入门

在 Objective-C 中,objc_objectobjc_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_classobjc_object 的关系

在 Objective-C 中,类本身也是对象。这意味着 objc_class 结构是 objc_object 结构的一个子类。每个类对象都有一个 isa 指针,指向其元类对象。元类对象也有一个 isa 指针,指向根元类对象。

类和元类关系图
+--------------------+      +--------------------+      +--------------------+
|    实例对象         | --> |    类对象            | --> |    元类对象          |
+--------------------+      +--------------------+      +--------------------+
|  isa -> Class      |      |  isa -> MetaClass  |      |  isa -> RootMetaClass|
+--------------------+      +--------------------+      +--------------------+
|                    |      |  super_class       |      |  super_class        |
+--------------------+      +--------------------+      +--------------------+
  1. 实例对象isa 指针指向类对象。
  2. 类对象isa 指针指向元类对象。
  3. 元类对象isa 指针指向根元类对象。

具体示例

以下是一个具体示例,展示如何使用 objc_objectobjc_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_objectobjc_class 的结构及其关系,有助于深入掌握 Objective-C 的运行时机制和面向对象编程模型。


拓展

objc_object 结构代表一个 Objective-C 对象,objc_class 结构代表一个类对象,那么什么结构代表元类对象 ?什么结构代表根元类对象 ?

在 Objective-C 中,类对象和元类对象实际上使用相同的结构体,即 objc_class 结构体。元类对象是特殊的类对象,用于存储类方法。当一个类对象调用类方法时,这个调用实际上是通过它的元类对象实现的。

类对象、元类对象和根元类对象

  1. 类对象:用于存储实例方法和实例变量。
  2. 元类对象:用于存储类方法。每个类对象都有一个对应的元类对象。
  3. 根元类对象:所有元类的终极元类,通常是 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 运行时的动态特性和面向对象编程模型非常重要。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

依旧风轻

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值