在encodeWithCoder:和initWithCoder之后指向现有对象:

时间:2018-01-27 20:27:18

标签: ios objective-c cocoa nscoding nscoder

NSCoding如何处理指向其他对象而不是值的指针的编码和解码?我有一系列需要编码的模型类,它们需要用弱属性相互引用。我很惊讶地发现编码后保留了引用,保存到文件,然后从文件中读取并解码。即使彼此引用的对象的内存地址发生了变化,这仍然有效。我很想知道NSCoding如何实现这一目标,并且还希望确保它能够始终如一地工作。

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

1 个答案:

答案 0 :(得分:2)

tl; dr:是的,SELECT m.SourceID, ( SELECT COALESCE((COUNT(*), 0) FROM dbo.Capture WHERE SourceID = m.SourceID) AS SourceCount FROM dbo.Capture m WHERE SourceID IN (37, 38, 130, 131, 132, 133) GROUP BY SourceID ) NSKeyedArchiver维护对象图中对象的引用关系;如果对对象引用其他对象的对象图进行编码,则可以期望以维护这些关系的方式对图进行解码。在编码和解码后,您不一定会得到相同的指针,但对象的身份将保持不变。

通过NSKeyedUnarchiver对对象进行编码时,-encodeObject:forKey:永远不会写出对象的指针地址。相反,它维护着一个独特的对象表,它曾经见过:

  1. 如果之前从未见过您正在编码的对象,则会将其添加到表中并分配UID。然后它NSKeyedArchiver调用它,以便它可以编码所有属性
  2. 如果之前已经看过(并且已经分配了UID),则没有任何反应(但UID会记录在其位置)
  3. 归档完成后,归档文件包含唯一的对象表以及表示对象图结构的另一个字典。代替对象的是UID。

    在解码时,当您致电-encodeWithCoder:时,-decodeObject:forKey:执行相反的映射:

    1. 查看归档中密钥的UID,并在唯一表中搜索UID。如果该对象之前已被解码,则返回对已解码对象的引用。这是关键部分 - 您不一定会在编码时编码的解码中获得相同的指针,但您将获得对同一对象的引用,而不是一份副本
    2. 如果以前从未解码过UID,它会在与UID对应的唯一表中查找编码对象,查找该类并调用NSKeyedUnarchiver+alloc-initWithCoder:在对象上。然后,该对象被记录在UID到对象的映射中,以便在必要时重用
    3. 这是密钥存档系统的关键功能之一,您可以依赖此维护行为。