问题
I was curious what is considered the better way to manage the reading and writing of a High Score plist file. My High Score class is:
@interface HighScore : NSObject <NSCoding> {
NSString *name;
int score;
int level;
int round;
NSDate *date;
}
Now, I could do method A, add NSCoding methods:
- (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
And write it all out with:
if (![NSKeyedArchiver archiveRootObject:highScoresList toFile:path]) ...
Reading it back in would be pretty straight forward. However the plist file, IMHO, looks like crap.
Or I could employ method 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];
}
and write it all out with:
if (![array writeToFile:path atomically:YES]) ...
Reading it back in is a tiny bit harder. But the plist file looks much cleaner (smaller and compact).
Any thoughts? Am I missing something that is much simpler? (I want to keep the High Scores separate from NSUserDefaults so I am not using that).
回答1:
Both your ways look fine to me. There is also Core Data in the 3.0 OS, although it might be overkill if all you want to save is a single high score value.
回答2:
I'm not sure that I understand your objections! Both should work just fine.
Personally I prefer method A. I think it makes sense that an object knows how to encode itself. It makes maintenance easier and any changes more localised. Plus it probably uses less memory.
回答3:
check out this question, maybe it's useful for your app
回答4:
I went with method B because: 1. The plist file is more readable and 2. I can save off some file and class version numbering into this method easily:
In my HighScore class:
- (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];
}
来源:https://stackoverflow.com/questions/896644/advice-on-high-score-persistence-iphone-cocoa-touch