简短版本:
我用(nonatomic, retain)定义了一个属性,并假定该属性将被保留。但是,除非我在为属性分配字典时调用retain,否则应用程序会崩溃,并出现EXEC BAD ACCESS错误。
长版本:
我有一套有字典的单身公寓。标头的定义如下
@interface BRManager : NSObject {
}
@property (nonatomic, retain) NSMutableDictionary *gameState;
+ (id)sharedManager;
- (void) saveGameState;
@end在实现文件中,我有一个在init中调用的方法。此方法从捆绑包中加载plist,并在设备上的users documents文件夹中创建它的副本。
- (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];
}这会在gameState上抛出一个EXEC BAD ACCESS错误。如果我修改loadGameState以保留gameState字典,一切都会正常工作。例如:
gameState = [[NSMutableDictionary dictionaryWithContentsOfFile:sourcePath] retain];我猜这是正确的行为,但为什么呢?(nonatomic, retain)的意思不是我想的那样,还是有别的东西在起作用?
我还没有真正摸索过内存管理,所以我总是偶然发现这个东西。
发布于 2012-05-03 18:31:56
您必须使用访问器:
self.gameState = [NSMutableDictionary dictionaryWithContentsOfFile:sourcePath];或者(相当于):
[self setGameState:[NSMutableDictionary dictionaryWithContentsOfFile:sourcePath]];而不是
gameState = [NSMutableDictionary dictionaryWithContentsOfFile:sourcePath];它只设置了ivar,而没有任何属性的概念。
发布于 2012-05-03 18:37:02
您在哪里将gameState声明为ivar?我假设你在实现中这样做了。
真正的问题是,在您的实现中,您直接访问gameState,而不是实际调用您声明的属性。为此,您必须向self发送适当的消息:
[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确保你有时间摸索那个memory management literature..。这是一个非常基本的问题,根据StackOverflow的严格规则,我不应该回答这个问题。祝好运!
https://stackoverflow.com/questions/10429099
复制相似问题