0

データをエンコード/デコードするために次のメソッドを作成しました。

- (void) encode: (BOOL) encodeBool int: (NSNumber *) integer boolean:(BOOL) boolean key: (NSString *) keyStr {

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *gameStatePath = [documentsDirectory stringByAppendingPathComponent:@"gameData"];



    if (encodeBool == YES) {

        NSMutableData *gameData = [NSMutableData data];
        NSKeyedArchiver *encoder = [[NSKeyedArchiver alloc] initForWritingWithMutableData:gameData];

        if (integer) {
            [encoder encodeInt:[integer intValue] forKey:keyStr];
        }
        else if (boolean) {
            [encoder encodeBool:boolean forKey:keyStr];
        }

        [encoder finishEncoding];
        [gameData writeToFile:gameStatePath atomically:YES];
        [encoder release];


    } else {

        NSMutableData *gameData = [NSData dataWithContentsOfFile:gameStatePath];

        if (gameData) {

            NSKeyedUnarchiver *decoder = [[NSKeyedUnarchiver alloc] initForReadingWithData:gameData];

            if (integer) {
                NSLog(@"%d", [decoder decodeIntForKey:keyStr]);
            }
            else if (boolean) {

                if ([decoder decodeBoolForKey:keyStr]==YES) {
                    NSLog(@"YES");

                } else {
                    NSLog(@"NO");
                }

            }



            [decoder finishDecoding];
            [decoder release];

        }


    }



}

そしていくつかのテスト

    [[GameData sharedData] encode:YES int: [NSNumber numberWithInt:100] boolean:NO key:@"testInt"];
    [[GameData sharedData] encode:YES int:nil boolean:YES key:@"bool"];        
    [[GameData sharedData] encode:YES int:[NSNumber numberWithInt:1030] boolean:nil key:@"test"];

    [[GameData sharedData] encode:NO int: [NSNumber numberWithInt:1]  boolean:nil key:@"testInt"];
    [[GameData sharedData] encode:NO int:nil boolean:YES key:@"bool"];
    [[GameData sharedData] encode:NO int:[NSNumber numberWithInt:100]  boolean:nil key:@"test"];

出力は

0
NO
1030

最後のものだけが正しいです..誰かが私が間違っていることを教えてもらえますか?ありがとう

4

2 に答える 2

2

問題は、メソッドを呼び出すたびにファイルを上書きすることです。つまり、前の呼び出しでエンコードした値を消去します。1回の呼び出しですべての値をエンコードするように、メソッドを書き直す必要があります。

1つの代替方法は、GameStateオブジェクトを作成して実装しNSCoding、それを読み取って+[NSKeyedArchiver archiveRootObject:toFile:]シリアル化し、で逆シリアル化すること+[NSKeyedUnarchiver unarchiveObjectWithFile:]です。そのためのコードは次のようになります。

@interface GameState : NSObject <NSCoding>

@property (nonatomic) int someInt;
@property (nonatomic) BOOL someBool;
@property (nonatomic, strong) NSString *someString;

@end

static NSString *const BoolKey = @"BoolKey";
static NSString *const StringKey = @"StringKey";
static NSString *const IntKey = @"IntKey";

@implementation GameState

- (id)initWithCoder:(NSCoder *)coder
{
    self = [super init];
    if (self) {
        _someBool = [coder decodeBoolForKey:BoolKey];
        _someInt = [coder decodeIntForKey:IntKey];
        _someString = [coder decodeObjectForKey:StringKey];
    }
    return self;
}

- (void)encodeWithCoder:(NSCoder *)aCoder
{
    [aCoder encodeBool:self.someBool forKey:BoolKey];
    [aCoder encodeInt:self.someInt forKey:IntKey];
    [aCoder encodeObject:self.someString forKey:StringKey];
}

@end

//  Somewhere in your app where reading and saving game state is needed...
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = nil;
if ([paths count]) {
    documentsDirectory = paths[0];
}
NSString *archivePath = [documentsDirectory stringByAppendingPathComponent:@"archive"];
GameState *gameState = [NSKeyedUnarchiver unarchiveObjectWithFile:archivePath];
if (!gameState) {
    gameState = [[GameState alloc] init];
    gameState.someString = @"a string";
    gameState.someInt = 42;
    gameState.someBool = YES;
}

//  Make changes to gameState here...

[NSKeyedArchiver archiveRootObject:gameState toFile:archivePath];
于 2013-02-25T04:36:04.607 に答える
2

最初の問題は、テストするときはif (boolean)、 と言うのと同じif (boolean == YES)です。Bool はオブジェクトではなく、 にすることもできませんnil。あなたがnilboolとして渡すとき、それは渡すのと同じNOです。ただし、これがすべての問題を説明しているとは思いません。ファイルも保存されていないと思います。

NSKeyedUnarchiver ドキュメントから:

アーカイブに存在しないキーを使用してこのクラスの decode... メソッドのいずれかを呼び出すと、正でない値が返されます。この値は、デコードされたタイプによって異なります。たとえば、キーがアーカイブに存在しない場合、decodeBoolForKey: は NO を返し、decodeIntForKey: は 0 を返し、decodeObjectForKey: は nil を返します。

これらは、取得している誤った値です。まず、エラー チェックを行っていないことに注意してください。何が失敗しているかを確認するためにいくつかのチェックを追加してみてください。たとえば、次のように試すことができます。

    [encoder finishEncoding];
    NSError *error;
    BOOL success = [gameData writeToFile:gameStatePath options:NSDataWritingAtomic error:&error];
    if (success == NO) NSLog(@"Error: %@", [error localizedDescription]);

エラーが発生したら、そこから先に進みます。

于 2013-02-25T04:29:06.010 に答える