2013-02-25 2 views
0

Я написал следующий метод для кодирования/декодирования данных ..NSCoding -decoder возвращает неправильные значения -iOS

- (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 

только последний правильный. Может ли кто-нибудь сказать мне, что я делаю неправильно? Спасибо

ответ

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]; 
2

Первая проблема, когда вы тестируете if (boolean), это то же самое, что и if (boolean == YES). Bools не являются объектами и не могут быть nil. Когда вы передаете nil в качестве bool, это то же самое, что и передать NO. Я не думаю, что это объясняет все ваши проблемы. Я думаю, что файл также не сохраняется.

Из документов NSKeyedUnarchiver:

Если вы вызываете один из расшифровывают ... Методы этого класса с использованием ключа , что не существует в архиве, неположительный значение возвращается. Это значение зависит от типа декодирования. Например, если в архиве нет ключа , 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]); 

После того, как вы получите сообщение об ошибке, мы можем пойти оттуда.

 Смежные вопросы

  • Нет связанных вопросов^_^