当前位置: 首页 > news >正文

iOS -- isa指针

  1. isa指针:isa指针是一个指向对象所属类或元类的指针。它决定了对象可以调用的方法和属性。isa指针在对象的结构中存在,并且在运行时会被自动设置。
  2. isa 指针,表示这个对象是一个什么类。而 Class 类型, 也就是 struct objc_class * ,这是苹果在下面的注释中写到的。这说明类本身也是一个对象。在类对象中的 isa 指向的类叫做“元类”,类方法就定义在元类中。总的来说就是,一个类可以有很多的实例,这些实例有着唯一的一个类对象,而这个类对象也有着唯一的一个元类。
  3. 在这里插入图片描述

在Objective-C中,每个对象都有一个isa指针,它指向该对象所属的类或元类。isa指针决定了对象可以调用的方法和属性。通过isa指针,Objective-C运行时可以在运行时动态地确定对象所属的类,并在该类或其父类中查找对应的方法实现。
下面是一些示例代码来说明isa指针的作用:

@interface MyClass : NSObject
- (void)myMethod;
@end@implementation MyClass
- (void)myMethod {NSLog(@"MyClass's myMethod");
}
@endint main() {MyClass *myObject = [[MyClass alloc] init];[myObject myMethod];return 0;
}

在上面的示例中,创建了一个名为MyClass的类,它继承自NSObjectMyClass类中定义了一个名为myMethod的方法。

当我们创建一个MyClass对象并调用myMethod方法时,实际上发生了以下过程:

  1. 分配内存并初始化MyClass对象。
  2. 运行时为该对象设置isa指针,使其指向MyClass的类对象。
  3. myObject上调用myMethod方法时,运行时首先通过isa指针找到MyClass的类对象。
  4. 运行时在类对象中查找名为myMethod的方法实现并执行。

通过这个过程,我们可以看到isa指针在动态确定对象所属的类的过程中起到了关键作用。它使得我们可以在运行时根据对象的实际类型来调用适当的方法。

isa,类对象,元类对象

OC的对象及其alloc和init。验证了OC对象底层是结构体,然后在alloc的方法调用栈的最后一个关键方法creatinstance中,有一个创建isa指针的方法。这篇,我们就先聊一聊isa指针。
我们知道,OC中的绝大部分对象,都是继承自NSObject(目前我已知的只有一个 NSProxy 类不继承自NSObject,它跟NSObject一样,是基类)。按住command键,跳进NSObject的头文件,就能看到下面的代码:

@interface NSObject <NSObject> {#pragma clang diagnostic push #pragma clang diagnostic ignored "-Wobjc-interface-ivars"Class isa  OBJC_ISA_AVAILABILITY;#pragma clang diagnostic pop
}

这就是NSObject的声明了,它只有一个isa指针,万物继承自NSObject,就有了自己的isa指针了。那这个isa到底有什么用呢?它究竟是个啥东西?

位域

在说isa之前,我们先了解一下[[共用体]]和[[位域]]这种技术。

在armv7、armv7s时代,由于是32位操作系统,苹果并没有对指针进行优化,实例对象的isa是直接指向类对象的。进入到arm64架构时代后isa占用8个字节,共计64位,如果只是单纯存一个指针太浪费,所以,苹果通过共用体技术,充分的让这64位存储了非常多的信息,不用再额外的开辟空间来存储,减少了内存开支,减少了内存的操作。下面我们具体看一下isa的结构。

isa的定义

union isa_t {isa_t() { }isa_t(uintptr_t value) : bits(value) { }Class cls;uintptr_t bits;
#if defined(ISA_BITFIELD)struct{ISA_BITFIELD;  // defined in isa.h  说明在isa.h中};
#endif
};

里面有个ISA_BITFIELD,再看这个是怎么定义的:

# if __arm64__
#   define ISA_MASK        0x0000000ffffffff8ULL
#   define ISA_MAGIC_MASK  0x000003f000000001ULL
#   define ISA_MAGIC_VALUE 0x000001a000000001ULL
#   define ISA_BITFIELD                                                      \uintptr_t nonpointer        : 1;          //表明这个属性占一位,且从低位开始\uintptr_t has_assoc         : 1;          // 同上                       \uintptr_t has_cxx_dtor      : 1;                                       \uintptr_t shiftcls          : 33; /*MACH_VM_MAX_ADDRESS 0x1000000000*/ \uintptr_t magic             : 6;                                       \uintptr_t weakly_referenced : 1;                                       \uintptr_t deallocating      : 1;                                       \uintptr_t has_sidetable_rc  : 1;                                       \uintptr_t extra_rc          : 19
#   define RC_ONE   (1ULL<<45)
#   define RC_HALF  (1ULL<<18)

isa union共用体中各个位的含义

  • nonpointer 指示位,表示是否对isa指针开启指针优化,值为0表示纯isa指针 1表示不止是类对象的地址,isa中还包含了类信息、对象的引用计数等

  • has_assoc: 关联对象标志位,0没有,1存在(KVO的实现原理)

  • has_cxx_dtor :该对象是否有C++或者Objc的析构器,如果有析构函数,则需要做析构逻辑,如果没有,则可以更快的释放对象

  • shiftcls: 实际存储类指针的值。开启指针优化的情况下,在arm64架构中有33位用来存储类指针,也是基于此,不同的架构中,对于类指针的读取需要不同的操作,在32位时期,由于,由于未进行isa优化,isa是直接指向类对象的,在64位之后,需要用isa指针与上掩码(ISA_MASK)才能取到指针,这个指针指向类对象。

  • magic :用于调试器判断当前对象是真的对象还是没有初始化的空间

  • weakly_refrenced: 对象是否被指向或者曾经指向一个ARC的弱变量,没有弱引用的对象,可以更快的释放

  • dellocating :标志对象是否正在释放对象。ing表示进行时

  • has_sidetable_rc:当对象引用计数大于0时,则需要借用该变量存储进位。weak的实现原理,就是使用sidetables。后续讲到内存管理的时候会对此进行详细的讲解。

  • extra_rc:当表示该对象的引用计数值,实际上是引用计数值减1.例如,如果对象的引用计数为10,那么extra_rc为9,如果引用计数大于10,则需要使用到上面的has_sidetable_rc。

用64位存储了这么多的信息,相当的高效!!我当初知道这个点的时候,叹为观止!苹果真的把这种细节这种设计做到了极致。苹果的工程师们真他娘的都是人才,各个身怀绝技(也可能我作为井底之蛙,没有了解过这个技术)。

好,介绍过isa之后,接下来就该是实例对象、类对象、和元类对象了。

在arm64架构之后,isa通过shiftcls来指向类对象的。类对象也是个对象,也有isa指针,它的isa中的shiftcls是指向元类对象的。元类对象也有isa,它的shiftcls都指向根类的元类对象。 网上有一张非常经典的图来展示了对象和元类对象的关系(这幅图将贯穿大部分关于底层原理的博客内容)来看一下:
在这里插入图片描述

这个图用语言来描述一下,就是

  • 实例对象的isa指向的类对象,类对象的isa指向元类对象。元类对象的isa均指向基类的元类对象(基类的元类对象的isa指向自己)。需要特别注意,arm64架构后,isa不直接指向,需要先用掩码取出shift_cls指针,这个是实际的指向关系的指针。
  • 类对象和元类对象中有superclass指针,普通类对象的superclass指针指向父类的类对象,基类类对象的superclass指向nil。基础对象的元类对象的superclass指针指向父类的元类对象,基类的superclass指针指向父类的类对象。

写完这些我都不认识这个类字了。谨记这幅图,就能非常好的理解实例对象、类对象、元类对象之间的关系了。这个图画的非常好,在后面的runtime的消息转发流程中还会用到这幅图以及这些对象之间的关系。

为什么需要类对象和元类对象

那为啥要有类对象和元类对象呢?类对象和元类对象中都放着什么东西呢?

先说为什么。我们都知道,我们创建的类,有很多的属性、协议和方法,方法又分为实例方法和类方法。而这些方法的实现都是统一的,再调用的过程中,只是参数的值不同,所以这些方法存一份儿就够了,没必要在每个对象中都存一份。所以就有了类对象和元类对象。可以想一下平时写的方法调用的代码,假定Person类有一个实例方法叫-(void)instanceFunction,有个类方法+(void)classFunction。我们在调用的时候是这么调用的:

- (void)callFunctions{[person instanceFunction];     //使用实例对象来调用实例方法[Person classFunction];        //使用类名(其实就是类对象)调用类方法
}

可以很明显的看出,方法调用者的不同。而这个不同就是由类对象、元类对象、isa来实现的。类对象中,存储了这个类的属性、协议和实例方法。元类对象中存储了这个类的类方法。在方法调用时,实例方法通过这个实例对象的isa找到这个类的对象,然后在类对象中查找这个方法。类方法通过类对象的isa找到这个类的元类对象,在元类对象中查找这个方法。通过这样的描述,结合上面的图,就能很好的理解isa指针、类对象和元类对象了。

好,简单的来总结一下今天的内容。主要是理清实例对象、类对象、元类对象之间的关系,要记住那副图,保证自己能完整的复述出他们之间的关系。isa就相当于纽带,将他们串联了起来。在最后提到了,类对象和元类对象是存储属性、协议和方法的,我们会在runtime中,具体的讲解这些信息是如何存储的。

相关文章:

iOS -- isa指针

isa指针&#xff1a;isa指针是一个指向对象所属类或元类的指针。它决定了对象可以调用的方法和属性。isa指针在对象的结构中存在&#xff0c;并且在运行时会被自动设置。isa 指针&#xff0c;表示这个对象是一个什么类。而 Class 类型&#xff0c; 也就是 struct objc_class * …...

【SA8295P 源码分析】14 - Passthrough配置文件 /mnt/vm/images/linux-la.config 内容分析

系列文章汇总见:《【SA8295P 源码分析】00 - 系列文章链接汇总》 本文链接:《【SA8295P 源码分析】14 - Passthrough配置文件 /mnt/vm/images/linux-la.config 内容分析》 透传配置文件位于:qnx.git\apps\qnx_ap\target\hypervisor\gvm\ivi\la\linux-la.config 它是在QNX Ho…...

新型糖基化氨基酸:Fmoc-Thr((Ac4Galβ1-3)Me,Ac4Neu5Acα2-6AcGalNAcα)-OH,化学CAS号174783-92-7

●英文名&#xff1a;Fmoc-Thr((Ac4Galβ1-3)Me,Ac4Neu5Acα2-6AcGalNAcα)-OH ●外观以及性质&#xff1a; Fmoc-Thr((Ac4Galβ1-3)Me,Ac4Neu5Acα2-6AcGalNAcα)-OH中通过对蛋白进行复杂蛋白糖基化修饰&#xff0c;细胞产生了极大丰度的蛋白质类型&#xff1b;通过对各类糖基…...

网络安全(黑客)怎么自学?

最近看到很多问题&#xff0c;都是小白想要转行网络安全行业咨询学习路线和学习资料的&#xff0c;作为一个培训机构&#xff0c;学习路线和免费学习资料肯定是很多的。机构里面的不是顶级的黑阔大佬就是正在学习的同学&#xff0c;也用不上这些内容&#xff0c;每天都在某云盘…...

Vue学习 之 MacOS 安装 webpack

Vue学习 之 MacOS 安装 webpack webpack 简介 Webpack 是一个非常流行的前端构建工具&#xff0c;它可以将多个模块&#xff08;包括CSS、JavaScript、图片等&#xff09;打包成一个或多个静态资源文件&#xff08;bundle&#xff09;&#xff0c;以便用于部署到生产环境。We…...

媒介易教你海外品牌推广:如何选择适合的新闻通稿发布平台?

在进行海外品牌推广时&#xff0c;选择合适的海外新闻通稿发布第三方平台是提高品牌曝光度和影响力的重要一环。这些平台可以帮助企业将新闻内容传播到全球范围内的媒体和受众&#xff0c;为品牌推广提供更广阔的机会。然而&#xff0c;选择合适的发布平台并不容易&#xff0c;…...

网络安全的学习路线是怎么样的?

最近看到网上有很多人在问诸如&#xff1a;“怎样成为网络安全工程师”等相关问题&#xff0c;这可能与近几年网络安全事件频发&#xff0c;国家对于互联网信息安全和互联网舆情的重视程度不断提升有关&#xff0c;网络信息安全工程师随之成为炙手可热的职业。关于职业前景的详…...

QT学习07:五种按钮控件

文章首发于我的个人博客&#xff1a;欢迎大佬们来逛逛 文章目录 抽象类&#xff1a;QAbstractButtonQPushButtonQToolButtonQCommandLinkButtonQRadioButtonQCheckBoxQButtonGroup 抽象类&#xff1a;QAbstractButton 是所有按钮类的祖先。 QAbstractButton的信号&#xff1a…...

chatgpt赋能python:Python如何截图运行结果

Python如何截图运行结果 介绍 Python是一种高级编程语言&#xff0c;非常流行。它具有许多有用的功能和库&#xff0c;使其成为许多开发人员的首选编程语言之一。但是&#xff0c;当您运行Python程序并需要与他人共享结果时&#xff0c;您可能需要截图运行结果。在本文中&…...

Baumer工业相机堡盟工业相机如何通过BGAPISDK使用JPEG图像压缩功能(C#)

Baumer工业相机堡盟工业相机如何通过BGAPISDK使用JPEG图像压缩功能&#xff08;C#&#xff09; Baumer工业相机Baumer工业相机BGAPISDK和JPEG图像压缩功能的技术背景Baumer工业相机通过BGAPISDK使用JPEG图像压缩功能1.引用合适的类文件2.使用BGAPISDK设置堡盟相机JPEG图像压缩模…...

RT-Thread FAL组件

目录 1、FAL介绍2、使用FAL2.1 下载FAL软件包2.2 FAL移植2.2.1 定义flash设备2.2.2 定义flash设备表&分区表2.2.3 加入到mdk工程3、MSH测试1、FAL介绍 FAL(Flash Abstraction Layer) Flash抽象层,是对Flash及基于Flash的分区进行管理、操作的抽象层,对上层统一了Flash及分…...

【git切换分支/tag】git stash保存暂不提交的更改

目录 问题git stash使用方法git stash pop 还原修改 git stash使用、修改指定tag的代码 其他git指令 问题 情景&#xff1a;分支1上开发新功能&#xff0c;临时切换到其他分支或tag上修改bug。 1、直接切换&#xff1a;如果没有冲突&#xff0c;分支1的修改会带到要切换的分支…...

【爬虫】4.5 实践项目——爬取当当网站图书数据

目录 1. 网站图书数据分析 2. 网站图书数据提取 3. 网站图书数据爬取 &#xff08;1&#xff09;创建 MySQL 数据库 &#xff08;2&#xff09;创建 scrapy 项目 &#xff08;3&#xff09;编写 items.py 中的数据项目类 &#xff08;4&#xff09;编写 pipelines_1.py …...

Socket 编程:基础概念辨析

文章目录 参考Socket APIBSD UNIX 操作系统BSD UNIX 与 Socket API Socket套接字套接字地址套接字 VS 套接字地址套接字的表示方法 TCP 套接字与 UDP 套接字TCP 套接字监听套接字连接套接字 UDP套接字 TCP 服务器端与 TCP 客户端通信的基本流程服务器端客户端 参考 项目描述刘…...

git lfs下载指定文件git lfs pull --include=“*.bin“

git lfs pull --include"*.bin"...

JavaScript 数组 函数

目录 1.数组的概念 2.创建数组 2.1 数组创建的方式 2.2利用new 创建数组 2.3 利用数组字面量创建数组 2.4 数据元素的类型 3.获取数组当元素 3.1数组元素的索引 4.遍历数组 4.1数组的长度 5.数组中新增元素 5.1通过修改length 长度新增数组元素 5.2通过修改数组索引…...

【哈佛积极心理学笔记】第7讲 逆境还是机遇

第7讲 逆境还是机遇 How can we raise base level? One of the things is coping, putting ourselves on the line. How to become an optimist. Optimism as an interpretation style, not as a Pollyannaish feel good kind of approach. Three approaches: First is to t…...

java springboot整合MyBatis做数据库查询操作

首先 我们还是要搞清楚 MyBatis 工作中都需要那些东西 首先是基础配置 你要连哪里的数据 连什么类型的数据库 以什么权限去连 然后 以 注解还是xml方式去映射sql 好 我们直接上代码 我们先创建一个文件夹 然后打开idea 新建一个项目 然后 按我下图的操作配置一下 然后点下一…...

11 二阶矩方法和Lovasz局部引理

文章目录 11 二阶矩方法和Lovasz局部引理11.1 The Second-Moment Method——二阶矩方法11.1.1 二阶矩方法定理11.1.2 二阶矩方法的应用——随机图阈值 11.2 Lovasz Local Lemma——Lovasz局部引理11.2.1 LLL定理11.2.2 LLL定理证明 11.3 Asymmetric LLL 11 二阶矩方法和Lovasz局…...

低代码赛道拥挤 生态聚合成为破局关键

在云计算和移动互联网的强劲推动下&#xff0c;企业数字化转型的步伐正在加速&#xff0c;对于软件应用开发的需求也呈现出爆发式的增长。这样的背景下&#xff0c;低代码平台凭借其独特的优势迅速崛起并引发了业界的广泛关注。 自2020年以来&#xff0c;低代码领域已成为投资…...

Spring Boot 实现流式响应(兼容 2.7.x)

在实际开发中&#xff0c;我们可能会遇到一些流式数据处理的场景&#xff0c;比如接收来自上游接口的 Server-Sent Events&#xff08;SSE&#xff09; 或 流式 JSON 内容&#xff0c;并将其原样中转给前端页面或客户端。这种情况下&#xff0c;传统的 RestTemplate 缓存机制会…...

【JavaSE】绘图与事件入门学习笔记

-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角&#xff0c;以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向&#xff0c;距离坐标原点x个像素;第二个是y坐标&#xff0c;表示当前位置为垂直方向&#xff0c;距离坐标原点y个像素。 坐标体系-像素 …...

Redis数据倾斜问题解决

Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中&#xff0c;部分节点存储的数据量或访问量远高于其他节点&#xff0c;导致这些节点负载过高&#xff0c;影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...

今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存

文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...

Mobile ALOHA全身模仿学习

一、题目 Mobile ALOHA&#xff1a;通过低成本全身远程操作学习双手移动操作 传统模仿学习&#xff08;Imitation Learning&#xff09;缺点&#xff1a;聚焦与桌面操作&#xff0c;缺乏通用任务所需的移动性和灵活性 本论文优点&#xff1a;&#xff08;1&#xff09;在ALOHA…...

Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?

在大数据处理领域&#xff0c;Hive 作为 Hadoop 生态中重要的数据仓库工具&#xff0c;其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式&#xff0c;很多开发者常常陷入选择困境。本文将从底…...

现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?

现有的 Redis 分布式锁库&#xff08;如 Redisson&#xff09;相比于开发者自己基于 Redis 命令&#xff08;如 SETNX, EXPIRE, DEL&#xff09;手动实现分布式锁&#xff0c;提供了巨大的便利性和健壮性。主要体现在以下几个方面&#xff1a; 原子性保证 (Atomicity)&#xff…...

【从零学习JVM|第三篇】类的生命周期(高频面试题)

前言&#xff1a; 在Java编程中&#xff0c;类的生命周期是指类从被加载到内存中开始&#xff0c;到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期&#xff0c;让读者对此有深刻印象。 目录 ​…...

云原生安全实战:API网关Kong的鉴权与限流详解

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关&#xff08;API Gateway&#xff09; API网关是微服务架构中的核心组件&#xff0c;负责统一管理所有API的流量入口。它像一座…...

HubSpot推出与ChatGPT的深度集成引发兴奋与担忧

上周三&#xff0c;HubSpot宣布已构建与ChatGPT的深度集成&#xff0c;这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋&#xff0c;但同时也存在一些关于数据安全的担忧。 许多网络声音声称&#xff0c;这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...