我有一个名为“Defense”的类,使用自定义init方法,如下所示:
// initialize the defense unit and add the sprite in the given layer
- (id) initWithType:(DefenseType)tType andInLayer:(CCLayer *)layer {
NSString *fileName;
fileName = [NSString stringWithUTF8String:defenseStructuresFile[tType]];
if ( (self = [super initWithFile:fileName]) ) {
type = tType;
maxHealth = defenseStructuresHealth[tType];
health = maxHealth;
mapRef = (SkirmishMap *)layer;
}
return self;
}
现在我正在使我的班级NSCoding
兼容,这需要以下两种方法:
- (id) initWithCoder:(NSCoder *)decoder
- (void) encodeWithCoder:(NSCoder *)encoder
当我通常分配一个“防御”实例时,我编码如下:
Defense *twr;
twr = [[Defense alloc] initWithType:type andInLayer:mapRef];
当我想恢复已保存的Defense对象实例时,我编码为
twr = [[decoder decodeObjectForKey:kDefense] retain];
但是在上面的代码中,我无法传递“type”和“mapref”参数,这些参数非常需要initialize
对象......
防御类派生自CCSprite
,由于CCSprite
不符合NSCoding
,因此可以通过(self = [super initWithFile:fileName])
方法调用initWithCoder
。但我需要type
参数来确定要传递给ccsprite's
initWithFile的文件名。
那么在这种情况下我该怎么做? 我应该改变班级设计吗?如果有,怎么样?
任何好的想法/建议都受到高度赞赏......:)
答案 0 :(得分:2)
您可以这样做:
- (id)initWithCoder:(NSCoder *)decoder
{
DefenseType earlyType;
NSString *filename;
earlyType = [decoder decodeIntegerForKey:@"defense"];
if (earlyType == somethingIllegal) {
[self release];
return nil;
}
// Now do something with earlyType do determine filename
self = [super initWithFilename:filename];
if (!self) return nil;
type = earlyType;
// Decode the rest.
return self;
}
输入您的方法(即使init
)后,始终会设置self
。它只是一个变量(或更确切地说:一个参数)。这就是[self release]; return nil;
即使在调用super
之前也能正常工作的原因。当您致电self = [super initWithFoo:];
时,您将覆盖self
。这样做是因为你的超类可能会[self release]; return nil;
或者分配一个具体的子类并返回它(当使用类集群时)。因此,在调用super的初始化程序之前,覆盖实例变量是不安全的,但是使用普通的堆栈变量(甚至全局变量)是可以的。