Советы по сохранению рекордов (iPhone, Cocoa Touch) - PullRequest
2 голосов
/ 22 мая 2009

Мне было любопытно, что считается лучшим способом управления чтением и записью файла списка рекордов. Мой класс рекордов:

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

Теперь я мог бы сделать метод A, добавить методы 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, ИМХО, выглядит как дерьмо.

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

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 выглядит намного чище (меньше и компактнее).

Есть мысли? Я скучаю по чему-то, что намного проще? (Я хочу отделить рекорды от NSUserDefaults, поэтому не использую это).

Ответы [ 4 ]

1 голос
/ 12 июня 2009

Оба ваших пути выглядят для меня прекрасно. В ОС 3.0 также есть Базовые Данные, хотя это может быть излишним, если все, что вы хотите сохранить, - это одно высокое значение.

1 голос
/ 12 июня 2009

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

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

0 голосов
/ 02 июля 2009

Я пошел с методом 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 голосов
/ 22 мая 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...