我使用(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属性。我假设(可能不正确)'retain'意味着将保留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)
是不是意味着我认为它意味着什么,或者是其他什么在这里发挥作用?
我还没有真正理解内存管理,所以我总是偶然发现这些东西。
答案 0 :(得分:5)
您必须使用访问者:
self.gameState = [NSMutableDictionary dictionaryWithContentsOfFile:sourcePath];
或(相当于):
[self setGameState:[NSMutableDictionary dictionaryWithContentsOfFile:sourcePath]];
而不是
gameState = [NSMutableDictionary dictionaryWithContentsOfFile:sourcePath];
只设置没有任何属性概念的ivar。
答案 1 :(得分: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
确保你到处寻找memory management literature ...这是一个非常基本的问题,根据StackOverflow的严格规则,我不应该回答。祝你好运!