【发布时间】:2013-11-13 19:09:38
【问题描述】:
我将CCSprite 子类化为可以编码和解码的对象。我想保存精灵状态并在特定位置再次加载它。除了使用NSKeyedUnarchiver 解码(参见下面的loadIconSpriteState)之外,一切似乎都很好,它给出了EXC_BAD_ACCESS 下面是代码:
HelloWorldLayer.h
@interface CCIconSprite : CCSprite {
NSString *iconName;
float iconXPos;
float iconYPos;
}
@property (nonatomic, retain) NSString *iconName;
@property (nonatomic, assign) float iconXPos;
@property (nonatomic, assign) float iconYPos;
+ (id)iconWithType:(NSString*)imageName;
- (id)initWithIconType:(NSString*)imageName;
@end
@interface HelloWorldLayer : CCLayer < NSCoding>
{
CCIconSprite* testSprite;
BOOL savedState;
CGSize size;
CCMoveTo* moveTo;
NSMutableArray* saveSpriteArray;
NSData* savedSpriteData;
}
+(CCScene *) scene;
@end
HelloWorldLayer.m:
CCIconSprite 实现:
@implementation CCIconSprite
@synthesize iconXPos;
@synthesize iconYPos;
@synthesize iconName;
+ (id)iconWithType:(NSString*)imageName
{
return [[[[self class] alloc] initWithIconType:imageName] autorelease];
}
- (id)initWithIconType:(NSString*)imageName
{
self = [super initWithFile:imageName];
if (!self) return nil;
iconName = imageName;
self.position = ccp(iconXPos, iconYPos);
return self;
}
编码和解码:
- (id)initWithCoder:(NSCoder *)decoder {
NSString* imageFileName = [decoder decodeObjectForKey:@"imageFileName"];
self = [self initWithIconType:imageFileName];
if (!self) return nil;
self.iconXPos = [decoder decodeFloatForKey:@"iconXPos"];
self.iconYPos = [decoder decodeFloatForKey:@"iconYPos"];
return self;
}
- (void)encodeWithCoder:(NSCoder *)encoder
{
[encoder encodeObject:iconName forKey:@"imageFileName"];
[encoder encodeFloat:self.iconXPos forKey:@"iconXPos"];
[encoder encodeFloat:self.iconYPos forKey:@"iconYPos"];
}
@end
HelloWorldLayer 实现:
@implementation HelloWorldLayer
+(CCScene *) scene
{
CCScene *scene = [CCScene node];
HelloWorldLayer *layer = [HelloWorldLayer node];
[scene addChild: layer];
return scene;
}
-(id) init
{
if( (self=[super init]) ) {
self.scale = 0.5;
savedState = NO;
size = [[CCDirector sharedDirector] winSize];
testSprite = [CCIconSprite spriteWithFile:@"Icon.png"];
testSprite.position = ccp(size.width/4, size.width/4);
testSprite.anchorPoint = ccp(0,0);
[self addChild:testSprite];
moveTo = [CCMoveTo actionWithDuration:3 position:ccp(3*size.width/4, 3*size.width/4)];
[testSprite runAction:moveTo];
[self schedule:@selector(saveAndLoadSpriteState)];
}
return self;
}
保存和加载状态:
-(void)saveIconSpriteState {
saveSpriteArray = [[NSMutableArray alloc] init];
[saveSpriteArray addObject:testSprite];
savedSpriteData = [NSKeyedArchiver archivedDataWithRootObject:saveSpriteArray];
}
-(void)loadIconSpriteState {
[NSKeyedUnarchiver unarchiveObjectWithData:savedSpriteData];
}
-(void)saveAndLoadSpriteState {
if ((testSprite.position.x > size.width/2) && !savedState) {
savedState = YES;
[self saveIconSpriteState];
}
else if ((testSprite.position.x == 3*size.width/4) && savedState) {
savedState = NO;
[self loadIconSpriteState];
[testSprite runAction:moveTo];
}
}
@end
编辑
设置异常断点后出现如下错误
Assertion failure in -[CCIconSprite initWithFile:]
指向行内:
NSAssert(filename != nil, @"Invalid filename for sprite");
在
-(id) initWithFile:(NSString*)filename
CCSprite.m 类的方法。
【问题讨论】:
-
它到底是在哪里崩溃的?如果您还没有启用异常断点。您是否单步检查了 imageName 是否正确编码/解码?你知道你正在使用 self.position = ccp(iconXPos, iconYPos);在 iconXYPos 被解码之前?你为什么不使用ARC?请做!
-
@LearnCocos2D:请参阅我添加的编辑。我还按照您的建议启用了 ARC。关于职位,我应该如何在使用它们之前对其进行解码?我不得不承认,我不太清楚自己是如何处理这些职位的。
-
你应该设置 self.position = ccp(iconXPos, iconYPos);读取变量后在 initWithCoder 中。
标签: cocos2d-iphone nsuserdefaults exc-bad-access nskeyedunarchiver