1

短縮版:

でプロパティを定義し、プロパティ(nonatomic, retain)が保持されると想定しました。しかしretain、辞書をプロパティに割り当てるときに呼び出さないと、アプリがEXEC BAD ACCESSエラーでクラッシュします。

長いバージョン:

辞書を持つシングルトンがあります。ヘッダーは次のように定義されます

@interface BRManager : NSObject {
}

@property (nonatomic, retain) NSMutableDictionary *gameState;

+ (id)sharedManager;
- (void) saveGameState;

@end

実装ファイルには、init で呼び出されるメソッドがあります。このメソッドは、バンドルから plist をロードし、デバイスのユーザー ドキュメント フォルダーにそのコピーを作成します。

- (void) loadGameState
{
 
    NSFileManager *fileManger=[NSFileManager defaultManager];
    NSError *error;
    NSArray *pathsArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
    NSString *doumentDirectoryPath=[pathsArray objectAtIndex:0];
    NSString *destinationPath= [doumentDirectoryPath stringByAppendingPathComponent:@"gameState.plist"];
    NSLog(@"plist path %@",destinationPath);    
    
    if (![fileManger fileExistsAtPath:destinationPath]){
        
        NSString *sourcePath=[[[NSBundle mainBundle] resourcePath]stringByAppendingPathComponent:@"gameStateTemplate.plist"];
        [fileManger copyItemAtPath:sourcePath toPath:destinationPath error:&error];
        
        gameState = [NSMutableDictionary dictionaryWithContentsOfFile:sourcePath];
                
    }else{
        gameState = [NSMutableDictionary dictionaryWithContentsOfFile:destinationPath];
    }
    
}

ここで、これが機能するはずだと私が考えた方法を示します。ヘッダーで、gameState プロパティを (非アトミック、保持) で定義します。「保持」とは gameState ディクショナリが保持されることを意味すると (おそらく間違って) 想定しました。ただし、シングルトン (saveGameState) には、AppDelegate -> ' applicationWillResignActive' のときに呼び出される別のメソッドがあります。

- (void) saveGameState
{
    NSArray *pathsArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
    NSString *doumentDirectoryPath=[pathsArray objectAtIndex:0];
    NSString *plistPath = [doumentDirectoryPath stringByAppendingPathComponent:@"gameState.plist"];
    [gameState writeToFile:plistPath atomically:YES];
}

EXEC BAD ACCESSこれにより、 でエラーがスローされgameStateます。gameState ディクショナリを保持するように loadGameState を変更すると、すべてが正常に機能します。例えば:

gameState = [[NSMutableDictionary dictionaryWithContentsOfFile:sourcePath] retain];

これは正しい動作だと思いますが、なぜですか?(nonatomic, retain)私が考えている意味ではありませんか、それとも何か他のことがここで働いていますか?

私はまだメモリ管理を本当に理解していないので、いつもこのようなことに出くわします。

4

2 に答える 2

6

アクセサーを使用する必要があります。

self.gameState = [NSMutableDictionary dictionaryWithContentsOfFile:sourcePath];

または (同等):

[self setGameState:[NSMutableDictionary dictionaryWithContentsOfFile:sourcePath]];

それ以外の

gameState = [NSMutableDictionary dictionaryWithContentsOfFile:sourcePath];

プロパティの概念なしで ivar のみを設定します。

于 2012-05-03T10:31:55.817 に答える
0

gameStateをivarとしてどこで宣言しますか?私はあなたが実装でそうしていると思います。

本当の問題は、実装では、gameStateに直接アクセスし、宣言したプロパティを実際には呼び出さないことです。そのためには、適切なメッセージを自分自身に送信する必要があります。

[self gameState]; // invokes the synthesized getter
[self setGameState:[NSMutableDictionary dictionaryWithContentsOfFile:sourcePath]]; // invokes the synthesized setter -- solves your problem

また

whatever = self.gameState; // invokes the getter
self.gameState = [NSMutableDictionary dictionaryWithContentsOfFile:sourcePath]; // invokes the synthesized setter -- solves your problem

そのメモリ管理の文献を調べてみてください...これは非常に基本的な質問であり、StackOverflowの厳格なルールに従って、私は答えるべきではありません。幸運を!

于 2012-05-03T10:37:02.387 に答える