四、浅谈isa

本文由快学吧个人写作,以任何形式转载请表明原文出处。

一、为什么要了解isa

isa是oc的一个非常重要的内容,所有的继承关系中都存在isa的身影,isa存储了非常多的有用信息,在继承,初始化,内存的分配上都有着重要的作用。

二、探究思路

1、找到isa的源码。

2、查看isa的本质。

3、查看isa相关的代码。

三、查找isa源码

需要的资料 : objc4-818.2 : github.com/LGCooci/KCO...

适配的环境是macos11.1,更高的版本的在上面的链接中也有可编译的源码。

1、初见isa是从alloc的源码分析中找到的,所以继续找alloc的源码。

2、打开818.2,在xcode的Navigator中搜索alloc {,找到alloc的源码。

3、进入源码实现 : alloc --> _objc_rootAlloc --> call_alloc --> _objc_rootAllocWithZone --> _class_createInstanceFromZone

4、第一篇文章中已经知道了isa的初始化会调用的是 : obj->initIsa(cls)。

5、进入obj->initIsa(cls),然后继续进入initIsa(cls,false,false)方法的实现。

6、找到isa。看方法最后的赋值 : isa = newisa;所以可以推断,newisa就是一个实例化的isa。

7、看newisa的类型isa_t。

四、isa的本质

从上一点可以看出,isa的本质是一个联合体,联合体的概念在这里。

1、isa结构简单分析

isa源码可以看第(三)节中的第7点中的图。

(1) isa的构造函数

isa有两个构造函数 :

第二个构造函数 : isa_t(uintptr_t value) : bits(value) { }是C++构造函数和初始化的组合写法,:后面是给成员bits赋值,参数就是小括号里面的value。

(2) isa的成员

isa有三个结构体成员,分别是 : uintptr_t bits;、Class cls和一个结构体。因为isa是一个联合体,所以cls和bits和结构体是不可能同时被赋值的。

bits和cls先不说,直接看isa结构体中的结构体成员,这是一个匿名的结构体。可以看到出现这个结构体成员的前提是宏定义了ISA_BITFIELD。所以全局搜索ISA_BITFIELD。

ISA_BITFIELD的源码图片。

从源码可以看出来,差别是在不同的处理器架构下,ISA_BITFIELD的宏定义内容不同。我们主要用的就是x86_64的就行。

所以看ISA_BITFIELD源码图片中的第三张图。

isa的匿名结构体是一个位域,里面的内容具体如下 :

yaml 复制代码
nonpointer : 表示是否对isa开启指针优化,1表示开启,那么isa中就包含了类信息、对象的引用计数等。0则表示纯isa指针,只保留了指向类的地址。

has_assoc : 关联对象标志位。1表示有,0表示没有。

has_cxx_dtor : 该对象是否有c++或者objc的析构器。1表示有,那么就需要做析构逻辑,0表示没有,那么对象就可以更快的释放。

shiftcls : 存储类指针的值。

magic  : 用于调试器来判断当前的对象是真的对象,还是只是一个没有初始化的空间。

weakly_referenced : 表示对象是否被指向或者曾经指向过一个ARC的弱变量。没有弱引用的对象可以更快的释放。

unused : 原来叫deallocating,现在改名字了。表示对象是否正在释放内存。

has_sidetable_rc : 当对象的引用计数大于10的时候,则需要借用该变量存储进位。

extra_rc : 表示引用计数的值,实际是引用计数的值-1。

关于extra_rc和has_sidetable_rc举例 : 如果对象的引用计数值为10,那么extra_rc就为9。如果引用计数值大于10,则使用has_sidetable_rc。

关于nonpointer,经常可以看到nonpointer,他的意思是非指针。如果为1,那么就证明这个对象的isa是一个不纯净的isa,它的一些信息会存储到上面的结构体里面,如果为0,证明是一个纯净的isa,那么isa存储的就只有cls,也就是一个指向父类的指针信息。

但是isa不是只能是nonponiter或者不是,指针的值也是可以存进上面的这个结构体中的。

五、isa的初始化

isa的初始化还是从alloc那里进入,和上面的第三节第4点里的一样,找到obj->initIsa(cls),进入initIsa。可以看到 :

继续进入initIsa。会发现这是一个objc_object的函数。所以应该全局搜索void initIsa( :

objc_object是对象的本质,这里先不说,先看初始化isa,一共有4个对isa的初始化函数。每一个都全局搜索一下,会发现它们最后全部都是实现initIsa函数。所以只需要看initIsa函数就够了。下图为initIsa函数的源码实现。

可以看到isa的结构体成员的赋值,都是在这里实现的。

相关推荐
andyweike5 天前
iOS语法原理
macos·objective-c·cocoa
青柠之夏cc6 天前
Kotlin Multiplatform:一次编写,全平台运行,2026 年跨平台开发的 “最优解”?
macos·objective-c·cocoa
黑科技iOS上架8 天前
iOS framework/dylib动态库定向加固实战
macos·ios·objective-c·cocoa·审核·ios混淆·执行程序差异化
程序鉴定师11 天前
2026年深圳小程序/App开发公司技术选型指南:从架构设计到交付标准全维度评估
java·小程序·uni-app·php·objective-c
鹤卿12313 天前
「iOS」GCD
开发语言·ios·objective-c
用户21816970493014 天前
FFmpeg (二) shell echo 数组
objective-c
2501_9159090620 天前
移动端开发工具链怎么组合比较好,iOS、Android、跨端三套配置方案
ide·vscode·ios·objective-c·个人开发·swift·敏捷流程
2501_9159184120 天前
iOS编程用什么软件好?主流工具Xcode、AppCode、CodeRunner与新兴快蝎对比
ide·vscode·ios·objective-c·个人开发·swift·敏捷流程
97650333521 天前
iOS 上架 4.3a 被拒【uniapp专讲】
flutter·ios·objective-c·uniapp·swift
黑化旺仔21 天前
【OC】KVO
macos·ios·objective-c·cocoa