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

第一个问题是当你测试时if (boolean)它和说一样if (boolean == YES)。布尔不是对象,也不能是nil. 当您nil作为布尔值传入时,它与传入相同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 回答
2

您的问题是,每次调用方法时,都会覆盖文件 - 删除您在之前调用中编码的值。您可能应该重写您的方法,以便在一次调用中对所有值进行编码。

一种替代方法是创建一个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 回答