2009-05-22 8 views
2

J'étais curieux de savoir quelle est la meilleure façon de gérer la lecture et l'écriture d'un fichier plist High Score. Ma haute classe Le score est:Conseils sur la persistance High Score (iPhone, Cocoa Touch)

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

Maintenant, je pourrais faire la méthode A, ajouter des méthodes 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 

Et tout écrire avec:

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

relisant dans serait assez simple. Cependant, le fichier plist, à mon humble avis, ressemble à de la merde.

Ou je pourrais employer la méthode 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]; 
} 

et écrire tout avec:

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

relisant en est un peu plus difficile minuscule. Mais le fichier plist est beaucoup plus propre (plus petit et compact).

Des pensées? Est-ce que je manque quelque chose qui est beaucoup plus simple? (Je veux séparer les scores élevés de NSUserDefaults, donc je n'utilise pas cela).

Répondre

0

Je suis allé avec la méthode B parce que: 1. Le fichier plist est plus lisible et 2. Je peux Épargnes de certains fichiers et la version classe de numérotation dans cette méthode facilement:

Dans ma classe 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

En fait, les méthodes NSCoding peuvent également effectuer des versions en utilisant la méthode de classe "+ (NSInteger)". C'est comme ça que je faisais des mises à niveau dans mon application. –

0

départ this question, peut-être il est utile pour votre application

1

vos deux façons regardez bien pour moi. Il y a aussi des données de base dans le système d'exploitation 3.0, même si cela peut être exagéré si tout ce que vous voulez sauvegarder est une seule valeur élevée.

1

Je ne suis pas sûr de comprendre vos objections! Les deux devraient fonctionner très bien.

Personnellement, je préfère la méthode A. Je pense qu'il est logique qu'un objet sache comment s'encoder lui-même. Il facilite la maintenance et tout changement plus localisé. De plus, il utilise probablement moins de mémoire.

Questions connexes