为什么Swift中两个不同__SwiftValue实例的ObjectIdentifier相同?
嘿,这个问题我刚接触Swift对象模型的时候也挠过头,咱们一点点说清楚~
首先得搞懂__SwiftValue的真实身份:Swift里的结构体、枚举这些值类型本质上不是Objective-C风格的对象,当你把它们强制转换成AnyObject的时候,Swift会偷偷把它们塞进一个叫__SwiftValue的私有包装类实例里——这就是你在LLDB里看到的那两个不同地址的玩意儿,它们确实是两个完全独立的包装器对象,内存地址不一样太正常了。
那为啥这俩不同的包装器,ObjectIdentifier会相同呢?核心秘密藏在ObjectIdentifier的实现逻辑里:它对__SwiftValue这种特殊的桥接包装类做了“特殊照顾”——不会傻乎乎地拿包装器自己的内存地址生成标识,而是会直接“穿透”这个包装层,去读取它包裹的原始值类型实例的唯一标识。
举个最典型的场景:如果你把同一个值类型实例多次转成AnyObject,每次可能都会生成一个新的__SwiftValue包装器(所以LLDB里看地址都不一样),但因为这些包装器裹的都是同一个原始值实例,所以ObjectIdentifier会返回相同的结果——这才符合咱们开发者的预期:我们关心的是那个值本身,不是Swift内部临时造的包装器。
哦对了,要是你像代码里那样用的是两个不同的实例(比如f1的i是1,f2的i是2),那它们的ObjectIdentifier应该是不同的,除非你遇到了Swift的某些极端优化场景(比如完全相同的值被复用)。但如果确实出现了不同包装器但ObjectIdentifier相同的情况,那大概率是因为这些包装器共享了同一个原始值实例。
最后再补个小知识点:ObjectIdentifier的设计初衷就是为了给对象/值提供一个逻辑上的唯一标识,而不是物理内存地址——对于桥接的__SwiftValue来说,这个逻辑就是“跟着原始值走”,而不是跟着临时包装器走。
备注:内容来源于stack exchange,提问作者HL666

