2009-05-22 2 views
2

Мне было любопытно, что считается лучшим способом управлять чтением и записью файла plist High Score. Мой высокий класс Score является:Советы по сохранению высокой оценки (iPhone, Cocoa Touch)

@interface HighScore : NSObject <NSCoding> { 
    NSString  *name; 
    int    score; 
    int    level; 
    int    round; 
    NSDate   *date; 
} 

Теперь, я мог бы сделать метод А, добавить методы NSCoding:

- (void) encodeWithCoder: (NSCoder *) coder { 
    [coder encodeObject: name 
       forKey: kHighScoreNameKey]; 
    [coder encodeInt: score 
       forKey: kHighScoreScoreKey]; 
    [coder encodeInt: level 
       forKey: kHighScoreLevelKey]; 
    [coder encodeInt: round 
       forKey: kHighScoreRoundKey]; 
    [coder encodeObject: date 
       forKey: kHighScoreDateKey]; 
} // encodeWithCoder 

- (id) initWithCoder: (NSCoder *) decoder { 
    if (self = [super init]) { 
     self.name = [decoder decodeObjectForKey: kHighScoreNameKey]; 
     self.score = [decoder decodeIntForKey: kHighScoreScoreKey]; 
     self.level = [decoder decodeIntForKey: kHighScoreLevelKey]; 
     self.round = [decoder decodeIntForKey: kHighScoreRoundKey]; 
     self.date = [decoder decodeObjectForKey: kHighScoreDateKey]; 
    } 
    return (self); 
} // initWithCoder 

И написать все это с помощью:

if (![NSKeyedArchiver archiveRootObject:highScoresList toFile:path]) ... 

Чтение его обратно в было бы довольно прямолинейно. Однако файл plist, ИМХО, выглядит как дерьмо.

Или я мог бы использовать метод Б:

NSMutableArray *array = [NSMutableArray arrayWithCapacity:20];; 
for (HighScore *hs in highScoresList) { 
    NSDictionary *dict = [[NSDictionary alloc] initWithObjectsAndKeys: 
          hs.name, kHighScoreNameKey, 
          [NSNumber numberWithInteger:hs.score], kHighScoreScoreKey, 
          [NSNumber numberWithInteger:hs.level], kHighScoreLevelKey, 
          [NSNumber numberWithInteger:hs.round], kHighScoreRoundKey, 
          hs.date, kHighScoreDateKey, 
          nil]; 
    [array addObject:dict]; 
    [dict release]; 
} 

и написать все это с помощью:

if (![array writeToFile:path atomically:YES]) ... 

Чтение его обратно в это чуть-чуть сложнее. Но файл plist выглядит намного чище (меньше и компактнее).

Любые мысли? Я пропустил что-то намного проще? (Я хочу, чтобы High Scores отличались от NSUserDefaults, поэтому я не использую это).

ответ

0

Я пошел с методом B, потому что: 1. Файл PLIST является более удобным для чтения и 2. Я могу спасти от некоторых файлов и классов нумерации версий в этот метод легко:

В моем классе HighScore:

- (id)initFromDictionary: (NSDictionary *)dict; 
{ 
    if (self = [super init]) { 
     self.name = [dict objectForKey:kHighScoreNameKey]; 
     self.score = [[dict objectForKey:kHighScoreScoreKey] integerValue]; 
     self.game = [[dict objectForKey:kHighScoreGameKey] integerValue]; 
     self.level = [[dict objectForKey:kHighScoreLevelKey] integerValue]; 
     self.date = [dict objectForKey:kHighScoreDateKey]; 
    } 
    return (self); 
} 
- (NSDictionary *)putIntoDictionary; 
{ 
    NSDictionary *dict = [[NSDictionary alloc] initWithObjectsAndKeys: 
          name, kHighScoreNameKey, 
          [NSNumber numberWithInt:score], kHighScoreScoreKey, 
          [NSNumber numberWithInt:game], kHighScoreGameKey, 
          [NSNumber numberWithInt:level], kHighScoreLevelKey, 
          date, kHighScoreDateKey, 
          nil]; 
    return dict; 
} 

And in my HighScoreTable class: 
- (id) load 
{ 
    NSString *path = [self getFilePath]; 

// [self clear]; 
    NSDictionary *rootLevelPlistDict = [NSDictionary dictionaryWithContentsOfFile:path]; 
    int versNum = [[rootLevelPlistDict objectForKey:kHighScoreVersKey] integerValue]; 

    if (versNum == kHighScoreVersNum) { 
     NSArray *insideArray = [rootLevelPlistDict objectForKey:kHighScoresKey]; 

     NSDictionary *dict; 
     for (dict in insideArray) { 
      HighScore *hs = [[HighScore alloc] initFromDictionary:dict]; 
      [highScoresList addObject:hs]; 
      [hs release]; 
     } 
    } 
    return sharedHighScoresSingleton; 
} 


- (void) save 
{ 
    if (!changed) 
     return; 
    NSString *path = [self getFilePath]; 
    NSMutableArray *array = [NSMutableArray arrayWithCapacity:kNumberOfHighScores]; 
    for (HighScore *hs in highScoresList) { 
     NSDictionary *dict = [hs putIntoDictionary]; 
     [array addObject:dict]; 
     [dict release]; 
    } 
    NSDictionary *rootLevelPlistDict = [[NSDictionary alloc] initWithObjectsAndKeys: 
      [[[NSBundle mainBundle] infoDictionary] 
       objectForKey:(NSString*)kCFBundleNameKey], kHighScoreAppNameKey, 
       [NSNumber numberWithInt:kHighScoreHeaderVersNum], kHighScoreHeaderVersKey, 
       [NSNumber numberWithInt:kHighScoreVersNum], kHighScoreVersKey, 
       [NSDate date], kHighScoreCreationKey, 
      array, kHighScoresKey, 
      nil]; 

    if (![rootLevelPlistDict writeToFile:path atomically:YES]) 
     NSLog(@"not successful in writing the high scores"); 
    [rootLevelPlistDict release]; 
} 
+0

На самом деле методы NSCoding также могут выполнять управление версиями с использованием метода класса «+ (NSInteger)». Вот как я делал обновления в своем приложении. –

0

чек из this вопрос, может быть, это полезно для вашего приложения

1

Оба ваши пути выглядят хорошо для меня. Существует также Core Data в ОС 3.0, хотя может быть слишком много, если все, что вы хотите сохранить, - это одна высокая оценка.

1

Я не уверен, что понимаю ваши возражения! Оба должны работать нормально.

Лично я предпочитаю метод А. Я думаю, что имеет смысл, что объект знает, как кодировать себя. Это упрощает обслуживание, а любые изменения локализуются. Плюс он, вероятно, использует меньше памяти.

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