0

NSKeyedArchiver を使用して NSData に変換し、それを NSUserDefaults に格納するオブジェクトがあります。オブジェクトが持つ配列の要素を除いて、すべてが正しく保存されます。配列内のすべてのオブジェクトは、NSCoder プロトコルに準拠しています (または、それらが呼ばれるものは何でも - 例self.property = [decoder decodeObjectForKey:@"key"] and [encoder encodeObjectForKey:@"key"]) 。

オブジェクトを保存すると、配列の要素は配列に残りますが、それらのプロパティ自体は保存されません。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

編集:「所有者」は、保存されているオブジェクトを参照します。ここに問題があると思うので、それを削除して再度テストしています。

編集:そしてそれは何もしませんでした!

4

4 に答える 4

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 に答える
1

あなたが説明することは「うまくいく」はずです。カスタム オブジェクトの encodeWithCoder メソッドでは、配列オブジェクトをエンコードするだけで、配列とその内容がエンコードされます。

ただし、配列内のいずれかのオブジェクトが NSCoding をサポートしていない場合、それは失敗します。私の推測では、配列内の何か (またはその子または孫) が NSCoding をサポートしていません。

于 2012-06-18T15:14:36.403 に答える
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"];

一方で、問題がそれほど単純なものであれば、何らかの警告が表示されることを期待しています。警告はありますか?他のプロパティのタイプを推測するのは難しいですが、同じ種類の問題について各プロパティを調べてください。

于 2012-06-18T15:29:26.080 に答える
0

found a workaround using a Unique-Id system for each mission and saving the progress for each mission separately into NSUserDefaults which are just then loaded again. Not ideal, but it works. Thanks for everyone's help!

于 2012-06-18T16:39:14.733 に答える