前言
最近看到一篇很有“意思”的文章 - iOS 中 copy 的原理。
文章第一段【属性中的 copy】提到 objc_copyStruct
objc_copyCppObjectAtomic
分别对应结构体和对象的拷贝。
本文将会通过将代码转换到中间码的方式,验证 llvm 对属性的 copy 处理逻辑。
普通结构体复制
下面,我们先写 Demo 验证一下结构体。
|
|
如下,编译器在产出中间代码时,会帮助开发者自动增加一个赋值方法 -[CopyMock setAStruct:]
。
|
|
该方法最终会调用 objc_copyStruct
函数进行复制操作,和 iOS 中 copy 的原理 对 结构体复制的描述一致。
(在实际场景,会存在一些特殊编译优化,后面有机会再讲)
普通字符串对象复制
下面,测试字符串属性的场景
|
|
在普通字符串场景下,代码会调用 objc_setProperty_nonatomic_copy
进行复制操作,而没有调用该文章提到的 objc_copyCppObjectAtomic
。
不同属性修饰符下的复制行为
实际上,在最新的 llvm 版本中,根据对象属性修饰符的不同,产出4种不同的方法调用。 如下所示,根据 copy 和 atomic 两个修饰符,我们很容易得到最终的复制函数。
|
|
总结
本文通过生成中间码的方式,分析了 llvm 对 结构体 和 对象 的 copy 处理逻辑。
- 结构体 通过
objc_copyStruct
进行复制操作 - 对象 通过
objc_setProperty_nonatomic_copy
及相关函数变体进行复制操作