Archiving documents in Cocoa
This is a programming convention in Cocoa and Objective-C to make documents persist their data across sessions.
Every NSObject-derived class is allowed to override -init or define/override -initWithParams: method to complete initialization for a newly created instance. If there are more than one way to initialize an object one of the -initX: methods should be doing most of the assignments, while the others will delegate specialized cases of initialization to that one 'designated' -initX:, which will also invoke the [super -init].
Here is what it looks like.
- (id) init { return [self initWithSomething:@"something"]; } - (id) initWithSomething: (NSString *) aSomething { if(self = [super init]) { _something = [aSomething copy]; } return self; }
Note that -initWithSomething: is a 'designated' initializer and is responsible to -init the super class first.
But there is an exception to this rule.
Archiving works by defining pairs of -encodeWithCoder: and -initWithCoder: methods. This is also known as NSCoding protocol - a convention to make persistence possible across Cocoa applications.
So, when decoding a saved document Cocoa expects the NSObject-derived class to implement -initWithCoder:, which is a flavor of a -initX: method.
The first class in a hierarchy of classes derived from NSObject will have its -initWithCoder: call [super -init] because NSObject does not implement NSCoding protocol. It will not call any other -initX: initializer even if there is one explicitely defined.
All other classes that are derived from a class with NSCoding protocol will have to replace [super -init] with a call to [super -initWithDecoder:]. This ensures that super properties are deserialized correctly. This breaks the -initX: pattern of 'designated' initializer.
In NSObject-derived class that implements NSCoding protocol:
- (void) encodeWithCoder:(NSCoder *) encoder { [encoder encodeObject: [self something] forKey: @"something"]; } - (id) initWithCoder:(NSCoder *) decoder { if(self = [super init]) { [self setSomething: [decoder decodeObjectForKey: @"something"]]; } return self; }
In classes, derived from other NSCoding classes that sit somewhere in the middle of hierarchy:
- (void) encodeWithCoder:(NSCoder *) encoder { [super encodeWithCoder: coder]; [encoder encodeObject: [self something] forKey: @"something"]; } - (id) initWithCoder:(NSCoder *) decoder { if(self = [super initWithCoder: coder]) { [self setSomething: [decoder decodeObjectForKey: @"something"]]; } return self; }












