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:
- If the object you're encoding has never been seen before, it gets added to the table and assigned a UID. It then has
-encodeWithCoder:
called on it so it can encode all of its properties
- If it's been seen before (and has been assigned a UID), nothing happens (but the UID is recorded in its place)
When 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:
- It looks at the UID for the key in the archive and searches for the UID in the unique table. If that object has been decoded before, it returns a reference to the decoded object. This is the key part — you won't necessarily get the same pointer on decode that was encoded on encode, but you'll get a reference to the same object instead of a copy
- If the UID's never been decoded before, it looks for the encoded object in the unique table corresponding to the UID, looks up the class and calls
+alloc
, -initWithCoder:
, and -awakeAfterUsingCoder
on the object. The object is then recorded in the UID-to-object map to be reused if necessary
This is one of the key features of the keyed archiver system, and you can rely on this behavior being maintained.