I think I'm missing something basic...
I implemented a class with NSCoding
and a child with NSCoding
too, but when I call the initWithCoder
of the child class , I get an InvalidArgument
error.
@interface Parent: NSObject<NSCoding>;
@implementation Parent
-(id)initWithCoder:(NSCoder *)decoder {
self = [[Parent alloc] init];
return self;
}
@end
@interface Child: Parent<NSCoding>;
@implementation Child
-(id)initWithCoder:(NSCoder *)decoder {
self = [super initWithCoder:decoder]; //self is Parent type here
// self = [[Child alloc] init]; if i do that, no error but no init for the parent'attribute
if(self){
self.childAttribute = [decoder decodeObjectForKey:@"KeyAttribute"]; // invalide argument ==> setChildAttribute doesn't exist.
}
return self;
}
I must have forgotten something basic, but I can't find out what... Anybody have an idea?
Thanks.
You are initializing Parent
in the wrong way. When -initWithCoder:
is called, the class has already been allocated. Remember the syntax:
id myObj = [[MyClass alloc] initWithArgument:...];
so it is assumed that within initializers you don't allocate, you set up default values.
You can refer to the ObjectiveC documentation to see how this should be done. I strongly recommend to check this out: Concepts in ObjC Programming – Object Initialization.
Also the Memory Management Guide can be very helpful. ObjectiveC relies on several conventions that you should be aware of to avoid leaks that might become difficult to track.
The right way of initializing your parent is:
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super init]; // it's just a subclass of NSObject
if (self) {
// DECODE VARIABLES...
}
return self;
}
If Parent
were a subclass of another NSCoding
-compliant class, [super init]
should have been replaced by [super initWithCoder:aDecoder]
; but in no case within an initializer you set self
to something that has not been returned by a superclass -init...
method.
You get the error because when you call [Child alloc]
, an instance of Child
is allocated, but then during initialization of Parent
you return the Parent
instance you manually allocated, therefore you lost the original reference to Child
and the class does not match anymore.