0

我有一个对象,我使用 NSKeyedArchiver 将其转换为 NSData,然后将其存储到 NSUserDefaults 中。除了对象拥有的数组元素之外,所有内容都被正确保存。数组中的所有对象都符合 NSCoder 协议(或任何他们所谓的 - 例如self.property = [decoder decodeObjectForKey:@"key"] and [encoder encodeObjectForKey:@"key"]

当我保存对象时,数组的元素保留在数组中,但它们的属性本身不会被保存。我确实调用了该sycnrhonize方法,所以这不是问题。

请注意,所有其他时间我保存并加载它是正确的,它只是不保存属于对象的数组的元素。我必须单独保存吗?

“当前状态” NSNumber 没有被保存。正在保存目标和目标

导入“级别.h”

@implementation Level
@synthesize objective = _objective;
@synthesize isComplete = _isComplete;
@synthesize goldReward = _goldReward;
@synthesize xpReward = _xpReward;
@synthesize missionID = _missionID;
@synthesize currentStatus = _currentStatus;
@synthesize targetName = _targetName;
@synthesize owner = _owner;

-(void)dealloc{

[super dealloc];
  }

-(id)initWithMissionID:(int)number{

if (self = [super init]) {
    self.currentStatus = 0;
    self.isComplete = NO;
    self.missionID = [NSNumber numberWithInt:number];
    [self setUpMisson];
}
return self;
}
-(void)setUpMisson{
if ([self.missionID intValue] == 0) {
    self.xpReward = [NSNumber numberWithInt:100];
    self.goldReward = [NSNumber numberWithInt:100];
    self.objective = [NSNumber numberWithInt:3];
    self.targetName = @"Swordsman";
    CCLOG(@"Gotta kill some swordsmen!");
}
}
-(void)encodeWithCoder:(NSCoder *)encoder{
[encoder encodeObject:self.objective forKey:@"objective"];
[encoder encodeObject:self.isComplete forKey:@"isComplete"];
[encoder encodeObject:self.goldReward forKey:@"goldReward"];
[encoder encodeObject:self.xpReward forKey:@"xpReward"];
[encoder encodeObject:self.missionID forKey:@"missionID"];
[encoder encodeObject:self.currentStatus forKey:@"currentStatus"];
[encoder encodeObject:self.targetName forKey:@"targetName"];
[encoder encodeObject:self.owner forKey:@"owner"];
CCLOG(@"SAVING LEVEL");
}
-(id)initWithCoder:(NSCoder *)decoder{
if (self = [super init]) {
    self.objective = [[decoder decodeObjectForKey:@"objective"]retain];
    self.isComplete = [[decoder decodeObjectForKey:@"isComplete"]retain];
    self.goldReward = [[decoder decodeObjectForKey:@"goldReward"]retain];
    self.xpReward = [[decoder decodeObjectForKey:@"xpReward"]retain];
    self.missionID = [[decoder decodeObjectForKey:@"missionID"]retain];
    self.targetName = [[decoder decodeObjectForKey:@"targetName"]retain];
    self.owner = [[decoder decodeObjectForKey:@"owner"]retain];
    CCLOG(@"LOADING LEVEL");
}
return self;
}
-(void)updateStatusForKill:(AI *)killedTarget{
CCLOG(@"WE KILLED: %@ and OUR GOAL IS: %@",killedTarget.name,self.targetName);

if ([killedTarget.name isEqualToString:self.targetName]) {
    [self setCurrentStatus:[NSNumber numberWithInt:[self.currentStatus intValue]+1]];
    CCLOG(@"Current Status: %i Objective: %i", [self.currentStatus intValue],[self.objective intValue]);
    if ([self.currentStatus intValue] == [self.objective intValue]) {
        [self completeMission];
    }
}
}
-(void)completeMission{
[self.owner setCoins:[NSNumber numberWithInt:[[self.owner coins]intValue] + [self.goldReward intValue]]];
[self.owner setXp:[NSNumber numberWithInt:[[self.owner xp]intValue] + [self.xpReward intValue]]];
CCLOG(@"complete");
[[self.owner missionList]removeObject:self];

}
@end

编辑:“所有者”指的是被保存的对象。我认为这就是问题所在,所以我将其删除并再次测试。

编辑:那什么也没做!

4

4 回答 4

1

您所描述的应该“正常工作”。在自定义对象的 encodeWithCoder 方法中,您只需对数组对象进行编码,这应该会导致数组及其内容被编码。

但是,如果数组中的任何对象不支持 NSCoding,那将失败。我的猜测是你的数组中的某些东西(或者它的孩子或孙子)不支持 NSCoding。

于 2012-06-18T15:14:36.403 回答
1

我在尝试保存包含属性值和另一个自定义对象的帐户数组时遇到了这个问题。我无法使用您提出的解决方案保存我的数据,因为我任意将帐户添加到数组中,并且为动态添加的帐户提供唯一标识符是没有意义的。我最终嵌套了 NSCoding 协议:

在我的AccountManager课堂上:

- (void) saveAllAccounts {
    [self deleteAllAccounts]; //Just removes whatever was previously stored there
    [[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:accountArray] forKey:saveAccountsArrayKey];
    [[NSUserDefaults standardUserDefaults] synchronize];
}

在我的Account课堂上:

- (void) encodeWithCoder:(NSCoder *)aCoder {
    [aCoder encodeObject:username forKey:@"username"];
    [aCoder encodeObject:token forKey:@"token"];
    [aCoder encodeObject:specialID forKey:@"special ID"];
    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:deviceArray];
    [[NSUserDefaults standardUserDefaults] setObject:data forKey:@"device array"];
}

- (id) initWithCoder:(NSCoder *)aDecoder {
    self = [super init];
    if (self != nil) {
        username = [[aDecoder decodeObjectForKey:@"username"] retain];
        token = [[aDecoder decodeObjectForKey:@"token"] retain];
        ecoID = [[aDecoder decodeObjectForKey:@"eco ID"] retain];
        NSData *deviceArrayData = [[NSUserDefaults standardUserDefaults] objectForKey:@"device array"];
        if (deviceArrayData != nil) {
            NSArray *savedArray = [NSKeyedUnarchiver unarchiveObjectWithData: deviceArrayData];
            if (savedArray != nil)
                deviceArray = [[NSMutableArray alloc] initWithArray:savedArray];
        }   
    }
    return self;
}

在我的AccountDevice课堂上:

- (void) encodeWithCoder:(NSCoder *)aCoder {
    [aCoder encodeObject:pairingPassword forKey:@"pairing password"];
    [aCoder encodeObject:devicePin forKey:@"device pin"];
}

- (id) initWithCoder:(NSCoder *)aDecoder {
    self = [super init];
    if (self != nil) {
        password = [[aDecoder decodeObjectForKey:@"password"] retain];
        pin = [[aDecoder decodeObjectForKey:@"pin"] retain];        
    }
    return self;
}  

它可能有点小错误,因为我还没有完成测试,但我的初步测试是成功的,我认为这个概念就在那里。

于 2012-07-16T18:18:14.057 回答
0

看起来您正在使用-encodeObject:forKey:甚至-decodeObjectForKey:不是对象的值。例如,在你的-initWithMissionID:你有:

self.isComplete = NO;

这让我认为这complete是一个BOOL属性,但你-encodeObject:forKey:说:

[encoder encodeObject:self.isComplete forKey:@"isComplete"];

我想你可能想打电话-encodeBool:forKey:,像这样:

[encoder encodeBool:self.isComplete forKey:@"isComplete"];

另一方面,如果问题如此简单,我真的希望得到某种警告。你有任何警告吗?推断您的其他属性的类型更难,但请查看您的每个属性以解决相同类型的问题。

于 2012-06-18T15:29:26.080 回答
0

为每个任务使用唯一 ID 系统找到了一种解决方法,并将每个任务的进度分别保存到 NSUserDefaults 中,然后再次加载。不理想,但它有效。感谢大家的帮助!

于 2012-06-18T16:39:14.733 回答