NSCoding 如何处理指向其他对象而不是值的指针的编码和解码?我有一系列需要编码的模型类,并且它们需要通过弱属性相互引用。我惊讶地发现,这些引用似乎在编码、保存到文件、然后从文件中读取并解码后得以保留。即使相互引用的对象的内存地址发生变化,这种方法仍然有效。我很想知道 NSCoding 如何实现这一点,并且也想确保它能够一致地工作。
简而言之:如果我对包含指向其他对象的指针的属性进行编码,我可以 100% 依赖解码后维护的引用吗?
最佳答案
tl;dr: 是的,NSKeyedArchiver
和 NSKeyedUnarchiver
维护对象图中对象的引用关系;如果您对其中对象引用其他对象的对象图进行编码,则可以期望以维护这些关系的方式对图进行解码。编码和解码后不一定会返回相同的指针,但对象的标识将保持不变。
当您通过 -encodeObject:forKey:
对对象进行编码时,NSKeyedArchiver
永远不会写出该对象的指针地址。相反,它维护一个之前见过的唯一对象表:
- 如果您正在编码的对象以前从未见过,则会将其添加到表中并分配一个 UID。然后调用
-encodeWithCoder:
以便对其所有属性进行编码 - 如果以前见过(并且已分配了 UID),则不会发生任何事情(但 UID 会记录在其位置)
归档完成后,归档文件包含唯一的对象表,以及表示对象图结构的另一个字典。 UID 代替了对象。
在解码时,当您调用 -decodeObject:forKey:
时,NSKeyedUnarchiver
会执行相反的映射:
- 它会查看存档中 key 的 UID,并在唯一表中搜索 UID。如果该对象之前已被解码,它将返回对已解码对象的引用。这是关键部分 - 您不一定会在解码时获得与编码时编码相同的指针,但您会获得对相同对象的引用,而不是一份副本
- 如果 UID 之前从未被解码,它会在 UID 对应的唯一表中查找编码对象,查找类并调用
+alloc
、-initWithCoder:
和对象上的-awakeAfterUsingCoder
。然后,该对象会记录在 UID 到对象映射中,以便在必要时重用
这是 key 归档系统的关键功能之一,您可以依赖这种行为的维护。
关于ios - : and initWithCoder: 之后指向现有对象的指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48480202/