ios - : and initWithCoder: 之后指向现有对象的指针

标签 ios objective-c cocoa nscoding nscoder

NSCoding 如何处理指向其他对象而不是值的指针的编码和解码?我有一系列需要编码的模型类,并且它们需要通过弱属性相互引用。我惊讶地发现,这些引用似乎在编码、保存到文件、然后从文件中读取并解码后得以保留。即使相互引用的对象的内存地址发生变化,这种方法仍然有效。我很想知道 NSCoding 如何实现这一点,并且也想确保它能够一致地工作。

简而言之:如果我对包含指向其他对象的指针的属性进行编码,我可以 100% 依赖解码后维护的引用吗?

最佳答案

tl;dr: 是的,NSKeyedArchiverNSKeyedUnarchiver 维护对象图中对象的引用关系;如果您对其中对象引用其他对象的对象图进行编码,则可以期望以维护这些关系的方式对图进行解码。编码和解码后不一定会返回相同的指针,但对象的标识将保持不变。

<小时/>

当您通过 -encodeObject:forKey: 对对象进行编码时,NSKeyedArchiver 永远不会写出该对象的指针地址。相反,它维护一个之前见过的唯一对象表:

  1. 如果您正在编码的对象以前从未见过,则会将其添加到表中并分配一个 UID。然后调用 -encodeWithCoder: 以便对其所有属性进行编码
  2. 如果以前见过(并且已分配了 UID),则不会发生任何事情(但 UID 会记录在其位置)

归档完成后,归档文件包含唯一的对象表,以及表示对象图结构的另一个字典。 UID 代替了对象。

在解码时,当您调用 -decodeObject:forKey: 时,NSKeyedUnarchiver 会执行相反的映射:

  1. 它会查看存档中 key 的 UID,并在唯一表中搜索 UID。如果该对象之前已被解码,它将返回对已解码对象的引用。这是关键部分 - 您不一定会在解码时获得与编码时编码相同的指针,但您会获得对相同对象的引用,而不是一份副本
  2. 如果 UID 之前从未被解码,它会在 UID 对应的唯一表中查找编码对象,查找类并调用 +alloc-initWithCoder: 和对象上的 -awakeAfterUsingCoder。然后,该对象会记录在 UID 到对象映射中,以便在必要时重用

这是 key 归档系统的关键功能之一,您可以依赖这种行为的维护。

关于ios - : and initWithCoder: 之后指向现有对象的指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48480202/

相关文章:

objective-c - 如何检测 Cocoa 应用程序何时从视网膜屏幕切换到非视网膜屏幕?

objective-c - 是否保存删除主菜单?

ios - IESLight 可以在 SceneKit 中转换阴影吗?

ios - 无法在 iOS 10 中使用分布式配置文件验证企业应用程序

ios - 如何在不绘制自己的情况下更改 UIPopoverPresentationController 箭头颜色

ios - 重新排序 UICollectionView + NSFetchedResultsController 中的单元格

objective-c - 在基于文档的应用程序中连接菜单项

ios - iOS 11 AVCaptureMetadataOutput 黑色条码上的反转/反转白色

objective-c - NSDirectoryFileType 已弃用。替代品是什么?

ios - 首次出现时无法更改 UITableViewCell 中 UILabel 的框架(使用自动布局)