6

iOS ゲームを作成しており、プレイヤーが到達した最高レベルを保存する必要があります。plist のデータ要素を正常に変更できますが、何らかの理由で、ゲームを再起動するたびにそのデータが元の値に戻り続けます。私のコードの基本的な流れは次のとおりです。

ゲームの初期化で、プレイヤーが到達した最高レベルを取得します (元の値は 1 です)。

pData = [[PlayerData alloc] init];
currentLevel = [[pData.data valueForKey:@"Highest Level"] intValue];
[self startNewLevel:currentLevel];

「data」は、PlayerData で次のように初期化される NSMutableDictionary です。

self.data = [NSMutableDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"playerdata" ofType:@"plist"]];

後で、プレーヤーが最高レベルを破った場合、「最高レベル」の値をインクリメントし、PlayerData で次の関数を呼び出してファイルに書き込みます。

-(void) newHighestLevel:(NSString*)path :(int)level{
     [self.data setValue:[NSNumber numberWithInt:level] forKey:path];
     [self.data writeToFile:@"playerdata.plist" atomically:YES]

プレイヤーがゲームのプレイ中にアクセスできるレベル メニューがあるため、これがすべて機能していることはわかっています。プレーヤーがレベル メニュー ボタンを押すたびに、レベル 1 から到達した最高レベルまでを表示する UITableView のサブクラスが作成されます。初期化は次のようになります。

levelMenu = [[LevelMenu alloc] init:[[pData.data valueForKey:@"Highest Level"] intValue]];

レベル メニューには、ゲーム中に正しいレベル数が表示されます (たとえば、プレーヤーがレベルをクリアしていない状態でレベル メニューに移動した場合、「レベル 1」と表示されますが、レベル 1 をクリアしてレベル メニューに移動した場合は、レベルメニューでは、「レベル1」と「レベル2」が表示されます)。ただし、アプリが終了するか、ユーザーがゲームのメイン メニューを終了すると、「最高レベル」の値が 1 に戻り、次のコードが実行されます。

currentLevel = [[pData.data valueForKey:@"Highest Level"] intValue];

プレイヤーがスタートを押すと、ユーザーがプレイ中にいくつのレベルを破ったかに関係なく、常に currentLevel を 1 に設定します。

値が元に戻るのはなぜですか? plist の編集を永続的にする何かが欠けていますか?

編集:

ここに私の新しい「newHighestLevel」メソッドがあります:

-(void) newHighestLevel:(NSString*)path :(int)level{
    [self.data setValue:[NSNumber numberWithInt:level] forKey:path];
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
    NSString *docfilePath = [basePath stringByAppendingPathComponent:@"playerdata.plist"];
    [self.data writeToFile:docfilePath atomically:YES];
    self.data = [NSMutableDictionary dictionaryWithContentsOfFile:docfilePath];
    BOOL write = [self.data writeToFile:docfilePath atomically:YES];
}

write は YES に設定されます。「docfilePath」を @"playerdata.plist" に変更すると、NO に設定されます。どちらの場合も、ゲームで何も変わらないようです。

解決:

-(void) newHighestLevel:(NSString*)path :(int)level{
      [self.data setValue:[NSNumber numberWithInt:level] forKey:path];
      NSString *basePath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
      NSString *docfilePath = [basePath stringByAppendingPathComponent:@"playerdata.plist"];
      [self.data writeToFile:docfilePath atomically:YES];
}

そして初期化で

-(id) init{

     NSString *basePath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
     NSString *docfilePath = [basePath stringByAppendingPathComponent:@"playerdata.plist"];
     NSFileManager *fileManager = [NSFileManager defaultManager];
     if (![fileManager fileExistsAtPath:docfilePath]){
         NSString *sourcePath = [[NSBundle mainBundle] pathForResource:@"playerdata" ofType:@"plist"];
         [fileManager copyItemAtPath:sourcePath toPath:docfilePath error:nil];
     }
     self.data = [NSMutableDictionary dictionaryWithContentsOfFile:docfilePath];
     return self;
}
4

2 に答える 2

13

plist から辞書を作成する最も簡単な方法は、メソッドdictionaryWithContentsOfFile:を使用することです。

たとえば、リソースから plist をロードするには、次のようにします。

NSString *filePath = [[NSBundle mainBundle] pathForResource:@"playerData" ofType:@"plist"];
NSMutableDictionary *plistdict = [NSMutableDictionary dictionaryWithContentsOfFile:filePath];

plistdict を書くのも同様に簡単です:

[plistdict writeToFile:filePath atomically:YES];

アプリのリソースに書き込むことはできないため、plist の Documents ディレクトリなどに別のパスを作成する必要があることに注意してください。

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
NSString *docfilePath = [basePath stringByAppendingPathComponent:@"playerData.plist"];
[plistdict writeToFile:docfilePath atomically:YES];

もう一度 plist からデータを取得します。

 NSMutableDictionary *plistdict = [NSMutableDictionary dictionaryWithContentsOfFile:docfilePath];

コンテンツを plistDict に追加して、再度書き込みます。

于 2012-09-05T04:43:32.053 に答える
3

メソッドは結果をwriteToFile:atomically返しますBOOL。ファイルがまったく保存されていないと思います。

ゲームが正しく動作する理由は、アプリケーションが毎回ファイルDictionaryから直接データを読み取るのではなく (1 回の起動時に読み込まれる)からデータを読み取るためです (また、そうすべきではありません)。plist

writeToFile:atomicallyファイルが実際に保存されているかどうかを判断するには、メソッドの戻り値を確認してください。

于 2012-09-05T04:49:44.273 に答える