2012-06-18 104 views
0

我有一个对象,我使用NSKeyedArchiver转换成NSData,然后将其存储到NSUserDefaults中。除了对象所具有的数组元素外,所有内容都可以正确保存。阵列中的所有对象都符合NSCoder协议(或其他所谓的协议,例如self.property = [decoder decodeObjectForKey:@"key"] and [encoder encodeObjectForKey:@"key"]NSUserDefaults与具有自定义对象数组的自定义对象

当我保存对象时,数组的元素仍保留在数组中,但它们的属性本身并未保存。我打电话给sycnrhonize方法,所以这不是问题。

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

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

进口“Level.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 

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

编辑:而且什么都没做!

+1

你能否为受影响的类显示你的'-encodeObjectForKey:'和'-decodeObjectForKey:'方法并告诉我们确切的哪些属性没有被保存? – Caleb

+0

肯定的事情,已更新 –

回答

0

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

1

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

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

+0

已检查,它只有一个对象,它支持NSCoding。我会发布我的实现代码,也许问题是 –

0

它看起来像你使用-encodeObject:forKey:-decodeObjectForKey:即使在不是对象的值。例如,在你的-initWithMissionID:你有:

self.isComplete = NO; 

这让我觉得completeBOOL属性,但您-encodeObject:forKey:说:

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

我想你也许想打电话-encodeBool:forKey:代替,像这样:

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

另一方面,我真的希望某种警告,如果p那么简单。你有任何警告吗?很难推断出其他属性的类型,但要查看每个属性的相同类型的问题。

+0

实际上我认为self.isComplete行它说'[NSNumber numberWithBool:NO]',但没有警告。其余的都是NSNumber或NSString –

+0

只有我能想到的将重置数字为0的方法是再次调用initWithNumber方法,因为这是它被设置为0的唯一位置。是否有可能以某种方式被称为? –

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; 
} 

它可能因为我还没有完成对我的测试,所以是一个小车吨,但我的初步测试是成功的,我认为这个概念就在那里。