2012-06-18 102 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; 
} 

它可能因爲我還沒有完成對我的測試,所以是一個小車噸,但我的初步測試是成功的,我認爲這個概念就在那裏。