【发布时间】:2012-05-03 09:59:41
【问题描述】:
短版:
我用(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];
}
这会在gameState 上引发EXEC BAD ACCESS 错误。如果我修改 loadGameState 以保留 gameState 字典,则一切正常。例如:
gameState = [[NSMutableDictionary dictionaryWithContentsOfFile:sourcePath] retain];
我猜这是正确的行为,但为什么呢? (nonatomic, retain) 不是我认为的意思,还是这里有其他东西在起作用?
我还没有真正了解内存管理,所以我总是偶然发现这些东西。
【问题讨论】:
标签: ios memory-management xcode4.2