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
@endint 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
@endint 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 运行时的动态特性和面向对象编程模型非常重要。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/44144.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python数据处理之高效校验各种空值技巧详解

概要 在编程中,处理空值是一个常见且重要的任务。空值可能会导致程序异常,因此在进行数据处理时,必须确保数据的有效性。Python 提供了多种方法来处理不同数据对象的空值校验。本文将详细介绍如何对Python中的各种数据对象进行空值校验,并包含相应的示例代码,帮助全面掌握…

高速电吹风方案介绍,多档温度风速调节,转速可达105000RPM

高速电吹风是这几年很火的一种电动小家电&#xff0c;能够在较短时间内完成头发干燥&#xff0c;减少对头发的热损伤。可以通过高速电机和风扇来产生高速风流&#xff0c;迅速将头发表面的水分吹干。高速电吹风通常配有多种档位风速和温度可以设置&#xff0c;用户可以根据需要…

大数据笔记--kafka工具AKHQ

目录 一、项目背景 二、项目目标 三、项目部署 1、前提条件 2、流程 2.1、准备工作 2.2、安装AKHQ 2.3、配置AKHQ 2.4、启动AKHQ 四、验证 一、项目背景 日常运维工作中&#xff0c;越来越多的团队成员&#xff0c;包括开发人员、数据分析师和业务运营团队&#xff0…

Linux——开发工具

1.yum yum是centos中的一个软件下载安装管理客户端&#xff0c;可以下载需要的软件或者解决依赖关系问题&#xff08;如动态库&#xff09;。程序都是来源于一段源代码&#xff0c;为了方便下载&#xff0c;源代码被提前在不同的环境下编译好生成对应的yum软件包&#xff0c;存…

运营商如何通过PCDN技术提高用户服务

随着网络技术的快速发展&#xff0c;用户对网络服务的要求也在不断提高。为了满足这些需求&#xff0c;运营商需要不断创新和优化自身的技术和服务。而 PCDN (Personal Content Delivery Network)技术作为一种新兴的内容分发网络解决方案&#xff0c;为运营商提高用户服务提供了…

k8s离线部署芋道源码后端

目录 概述实践Dockerfilek8s部署脚本 概述 本篇将对 k8s离线部署芋道源码后端 进行详细的说明&#xff0c;对如何构建 Dockerfile&#xff0c;如何整合 Nginx&#xff0c;如何整合 ingress 进行实践。 相关文章&#xff1a;[nacos在k8s上的集群安装实践] k8s离线部署芋道源码前…

Ubuntu20.04搭建嵌入式linux网络加载内核、设备树和根文件系统

文章目录 Ubuntu20.04搭建嵌入式linux网络加载内核、设备树和根文件系统TFTP服务搭建测试 NFS服务搭建测试 uboot配置TFTP服务搭建测试 NFS服务搭建测试 U-BOOT配置 Ubuntu20.04搭建嵌入式linux网络加载内核、设备树和根文件系统 TFTP服务搭建 sudo apt install tftpd-hpa su…

智能车载防窒息系统设计

摘要 随着汽车行业的快速发展&#xff0c;车辆安全问题越来越受到人们的关注。其中&#xff0c;车载防窒息系统是一项重要的安全设备。本论文基于STM32单片机&#xff0c;设计了一种智能车载防窒息系统。该系统主要包括氧气浓度检测模块、温湿度检测模块、声音检测模块、光线检…

『ComfyUI』从小白到入门全套教程,奶奶看了都会了!赶紧收藏!

本文简介 Stable Diffusion WebUI 应该是大多数人第一次接触 SD 绘画的工具&#xff0c;这款工具简单易上手&#xff0c;但操作流程相对固定。如果你想拥有更自由的工作流&#xff0c;可以试试 ComfyUI。而且很多新的模型和功能在刚出现时 ComfyUI 的支持度都比较高&#xff0…

拥抱应用创新,拒绝无谓的模型竞争

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

TikTok海外运营,云手机多种变现方法

从现阶段来看&#xff0c;TikTok 的用户基数不断增长&#xff0c;已然成为全球创业者和品牌的全新竞争舞台。其用户数量近乎 20 亿&#xff0c;年轻用户占据主导&#xff0c;市场渗透率也逐年提高。不管是大型企业、著名品牌&#xff0c;还是个体创业者&#xff0c;都绝不能小觑…

matlab 有倾斜的椭圆函数图像绘制

matlab 有倾斜的椭圆函数图像绘制 有倾斜的椭圆函数图像绘制xy交叉项引入斜线负向斜线成分正向斜线成分 x^2 y^2 xy 1 &#xff08;负向&#xff09;绘制结果 x^2 y^2 - xy 1 &#xff08;正向&#xff09;绘制结果 有倾斜的椭圆函数图像绘制 为了确定椭圆的长轴和短轴的…

最新Wireshark查看包中gzip内容

虽然是很简单的事情&#xff0c;但是网上查到的查看gzip内容的方法基本都是保存成zip文件&#xff0c;然后进行二进制处理。 其实现在最新版本的Wireshark已经支持获取gzip内容了。 选中HTTP协议&#xff0c;右键选择[追踪流]->[HTTP Stream] 在弹出窗口中&#xff0c;已…

从“技术驱动”向“应用驱动”

李彦宏在2024世界人工智能大会上的发言深刻揭示了当前AI技术发展的核心趋势与方向&#xff0c;强调了从“技术驱动”向“应用驱动”转变的重要性&#xff0c;这一观点极具前瞻性和实践指导意义。 对李彦宏发言的理解 技术与应用并重&#xff0c;但应用为先&#xff1a;李彦宏指…

前端开发者的算法修炼:10道经典算法题解析

在前端开发领域&#xff0c;扎实的算法基础不仅能提升代码质量&#xff0c;还能在面试中大放异彩。本文将精选10道前端开发者常见的算法题&#xff0c;并附上详细的解析&#xff0c;帮助你巩固算法知识&#xff0c;提高问题解决能力。 1. 数组扁平化 题目&#xff1a;给定一个…

为何Expo成为React Native官方推荐框架?

在React Conf上&#xff0c;我们更新了关于构建React Native应用的最佳工具指南&#xff1a;一个React Native框架——一个工具箱&#xff0c;包含所有必要的API&#xff0c;让你可以构建生产就绪的应用。 现在&#xff0c;使用React Native框架&#xff08;如Expo&#xff09…

SQL Server设置端口:跨平台指南

在使用SQL Server时&#xff0c;设置或修改其监听的端口是确保数据库服务安全访问和高效管理的重要步骤。由于SQL Server可以部署在多种操作系统上&#xff0c;包括Windows、Linux和Docker容器等&#xff0c;因此设置端口的步骤和方法也会因平台而异。本文将为您提供一个跨平台…

Xubuntu24.04之图形界面挂载硬盘(二百六十二)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

Unity入门之重要组件和API(4) : Input

前言 Input类主要处理用户输入设备相关操作&#xff1b;输入设备包括鼠标、键盘、触屏、手柄、陀螺仪(重力感应)。 1.鼠标 1.1鼠标在屏幕的位置 print(Input.mousePosition); 1.2检测鼠标输入 0-左键 1-右键 2-中键 if (Input.GetMouseButtonDown(0)) {print("鼠标…

Linux操作系统上用到的磁盘分区管理工具

parted磁盘分区工具 磁盘格式&#xff1a;MBR, GPT, 这两种名称分别是硬盘里面分区表两种格式的称呼&#xff0c; 第一种MBR格式的分区表最大支持2TB的容量&#xff0c; 磁盘的三种分区主分区&#xff0c;扩展分区&#xff0c;逻辑分区&#xff0c;主分区扩展分区<4 第…