How does NSCoding deal with encoding and decoding of pointers to other objects rather than values? I have a range of model classes which I need to encode, and they need to reference each other with weak properties. I was surprised to find that the references seemed to be maintained after encoding, saving to a file, then subsequently reading from the file and decoding. This worked even though the memory addresses of the objects which referenced each other changed. I'm interested to know how NSCoding achieves this, and also want to ensure it will work consistently.
In short: if I encode properties containing pointers to other objects, can I rely 100% on the references being maintained after decoding?
tl;dr: Yes, NSKeyedArchiver
and NSKeyedUnarchiver
maintain the reference relationships of the objects in your object graph; if you encode an object graph where objects reference other objects, you can expect the graph to be decoded in a way that maintains those relationships. You won't necessarily get back the same pointers after encoding and decoding, but the identities of the objects will remain the same.
When you encode an object via -encodeObject:forKey:
, NSKeyedArchiver
never writes out the pointer address of the object. Instead, it maintains a unique table of objects it's seen before:
-encodeWithCoder:
called on it so it can encode all of its propertiesWhen archiving is complete, the archive contains the unique table of objects, along with another dictionary that represents the structure of the object graph. In place of objects are UIDs.
On decode, when you go to call -decodeObject:forKey:
, NSKeyedUnarchiver
does the opposite mapping:
+alloc
, -initWithCoder:
, and -awakeAfterUsingCoder
on the object. The object is then recorded in the UID-to-object map to be reused if necessaryThis is one of the key features of the keyed archiver system, and you can rely on this behavior being maintained.