4

If I pass a super class object into -archivedDataWithRootObject:, but that object contains a subclass of the said super class; will that whole object graph be serialized to include the instance variables of the subclass or only the instance variables related to the super class?

Example:

@interface Mammal : NSObject

@property (nonatomic, copy) NSString *species;

@end

@interface Person : Mammal

@property (nonatomic, copy) NSString *name;

@end

Person *person = [[Person alloc] init];
person.species = @"Human";
person.name = @"Michael";

Mammal *mammal = person;

NSData *personData = [NSKeyedArchiver archivedDataWithRootObject:mammal];

Will the unarchived data only contain the Mammal instance variables?

Michael
  • 6,561
  • 5
  • 38
  • 55

1 Answers1

3

First, the static type of the variable holding the object pointer doesn't matter at all after compilation. That is, the fact that the mammal variable was declared as a pointer to Mammal is only used at compile time to check stuff. That fact does not survive in the compiled program and doesn't affect behavior at run time.

Second, neither NSKeyedArchiver nor its +archivedDataWithRootObject: method know how to archive the object that's passed in. They rely on the object knowing how to archive itself. An object must be of a type which conforms to the NSCoding protocol. Its class must implement the -encodeWithCoder: method. The specifics of how an object is encoded/archived is entirely up to the implementation of that method.

So, both Mammal and Person would have to override that method to encode the specific data for the respective class in order for either to be archived properly.

Once they do that, the normal dynamic dispatch of method invocations will result in the proper one being called on the object passed to +archivedDataWithRootObject:. Again, that depends on the dynamic type of the object, not the static type of the variable which holds a pointer to it.

Ken Thomases
  • 88,520
  • 7
  • 116
  • 154
  • Is there a default `-encodeWithCoder:` implementation? If you don't define it for an object, will it just throw an exception? – A O Oct 24 '15 at 06:23
  • 1
    No, there's no default implementation. If you don't define it for a class and the class doesn't inherit an implementation, then attempts to encode instances of that class will throw an exception, yes. However, it's all too easy to inherit an implementation from a superclass but forget to override it to add the proper encoding behavior for the subclass. So, if you implement it for `Mammal` but forget to override and extend it in `Person`, then archiving an instance of `Person` will only record mammal-relevant data and no person-relevant data. – Ken Thomases Oct 24 '15 at 06:51