解码器与NSString崩溃

时间:2011-03-18 14:42:50

标签: nscoder

我有一个保存分数的课程:

#import "cocos2d.h"

@interface ScoreData : NSObject<NSCoding> {

    NSString *playerName;
    NSDate *playDate;
}
-(NSString* )description;
@property (nonatomic, retain) NSString *playerName;
@property (nonatomic, retain) NSDate *playDate;
@end


#import "GameData.h"

@implementation ScoreData
@synthesize playerName;
@synthesize playDate;

#define kPlayerNameKey      @"PlayerName"
#define kPlayDateKey        @"playDate"

-(id)init
{  
    if( (self = [super init]) ) {

    }

    return self;
}

- (void) encodeWithCoder:(NSCoder *)encoder
{
    [encoder encodeObject:self.playerName
                   forKey:kPlayerNameKey];
    [encoder encodeObject:self.playDate
                   forKey:kPlayDateKey];
}

- (id)initWithCoder:(NSCoder *)decoder 
{
    ScoreData *highScoreData = [[ScoreData alloc] init];
    highScoreData.playerName = [[decoder decodeObjectForKey:kPlayerNameKey] string];
    highScoreData.playDate = [[decoder decodeObjectForKey:kPlayDateKey] date];

    return highScoreData;
}

@end

在我的GameLayer中,我打电话来保存这样的分数:

@interface GameLayer : CCLayer 
{
    ScoreData *scoreData;
}

-(void)gameOver
{
    scoreData.playerName = @"test";
    scoreData.playDate = [NSDate new];

    [[GameDataManager sharedGameDataManager] updateLocalScore:scoreData];
}

保存数据的代码:

-(void)updateLocalHighScore:(ScoreData *)scoreData
{
    [highScoreDataArray addObject:scoreData];

    NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
    [dic setObject:self.highScoreDataArray
            forKey:@"LocalHighScoreData"];

    [self writeApplicationData:dic bwriteFileName:@"teste.plist"];
}

-(BOOL) writeApplicationData:(NSDictionary *)data 
              bwriteFileName:(NSString *)fileName
{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    if (!documentsDirectory) {
        NSLog(@"Documents directory not found!");
        return NO;
    }

    NSString *appFile = [documentsDirectory stringByAppendingPathComponent:fileName];

    NSMutableArray *a = [[NSMutableArray alloc] init];
    a = [data objectForKey:@"ScoreData"];

    NSMutableData *_data = [[NSMutableData alloc] init];
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:_data];          
    [archiver encodeObject:data forKey:@"GameData"];
    [archiver finishEncoding];
    [_data writeToFile:appFile atomically:YES];
    [archiver release];
    [data release];

    return YES;
}

数据已正确保存......

然后我尝试从plist中读取数据:

-(BOOL) readApplicationData:(NSString *)fileName
{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *appFile = [documentsDirectory stringByAppendingPathComponent:fileName];
    NSData *myData = [[[NSData alloc] initWithContentsOfFile:appFile] autorelease];

    if (myData == nil) {

        return NO;
    }

    NSKeyedUnarchiver *un = [[NSKeyedUnarchiver alloc] initForReadingWithData:myData];
    NSMutableDictionary *dic = [un decodeObjectForKey:@"GameData"];

    self.highScoreDataArray = [dic objectForKey:@"ScoreData"];

    [un finishDecoding];
    [un release];

    return YES; 
}

但应用程序崩溃了:

- (id)initWithCoder:(NSCoder *)decoder 
{
    ScoreData *highScoreData = [[ScoreData alloc] init];
    highScoreData.playerName = [[decoder decodeObjectForKey:kPlayerNameKey] string];

    return highScoreData;
}

说: [4011:207] - [NSCFString string]:无法识别的选择器发送到实例0x544dd10 [4011:207] * 由于未捕获的异常'NSInvalidArgumentException'而终止应用程序,原因:' - [NSCFString string]:无法识别的选择器发送到实例0x544dd10'

任何人都可以帮助我离开这里。感谢^ _ ^

1 个答案:

答案 0 :(得分:2)

嗯,错误信息说明了一切。您在-string上调用NSString方法,由于此方法不存在,您的应用会崩溃。此外,-string-date消息完全没有必要。只需删除它们。

您的代码中存在更多问题:例如:您通常不应在-initWithCoder:中分配新对象。如果这样做,就会发生内存泄漏。该方法应如下所示:

- (id)initWithCoder:(NSCoder *)decoder 
{
    self = [super init];
    if (self != nil) {
        self.playerName = [decoder decodeObjectForKey:kPlayerNameKey];
        self.playDate = [decoder decodeObjectForKey:kPlayDateKey];
    }
    return self;
}

我还没有检查你的其余代码,因此很可能会有更多错误。