This is a great question, and I always wondered about it myself. So, I wrote a small test program to try it out. Four classes: ClassA
, ClassB
, ClassC
, and MyBaseClass
. ClassA
, ClassB
, and ClassC
inherit from MyBaseClass
which conforms to NSCoding
and provides two properties: name
and age
. The A, B, and C classes are identical except that ClassA
and ClassB
also contain a reference to an instance of ClassC
. ClassA
and ClassB
also override initwithCoder:
and encodeWithCoder:
to decode and encode their references to the instance of ClassC
. Here is what the top-level code looks like:
ClassA *a = [[ClassA alloc] initWithName:@"Mr. A" age:11];
ClassB *b = [[ClassB alloc] initWithName:@"Mrs. B" age:22];
ClassC *c = [[ClassC alloc] initWithName:@"Ms. C" age:33];
b.c = c;
a.c = c;
NSArray *rootObject = @[a, b, c];
NSString *const kFilePath = @"/Users/myname/Documents/testarchive";
BOOL result = [NSKeyedArchiver archiveRootObject:rootObject toFile:kFilePath];
NSLog(@"result = %@", (result) ? @"YES" : @"NO");
NSArray *newRootObject = [NSKeyedUnarchiver unarchiveObjectWithFile:kFilePath];
NSLog(@"new root object = %@", newRootObject);
The objects serialize and deserialize perfectly. Also, after deserializing, a.c
and b.c
point to the same instance of ClassC
— that is, their object pointers have the same address.
Apparently, within NSKeyedArchiver
's encodeObject:forKey:
, a test is done to see if the object being encoded isEqualTo:
a previously encoded object, and if it is, a reference is stored instead of a complete object. The converse must happen in NSKeyedUnarchiver
's decodeObject:forKey:
. Very cool!