简洁版本:
我定义了一个属性,(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
. 如果我修改 loadGameState 以保留 gameState 字典,则一切正常。例如:
gameState = [[NSMutableDictionary dictionaryWithContentsOfFile:sourcePath] retain];
我猜这是正确的行为,但为什么呢?(nonatomic, retain)
并不意味着我认为的意思,或者这里有其他东西在起作用?
我还没有真正了解内存管理,所以我一直偶然发现这些东西。