【问题标题】:Why do I have to retain a property despite using (nonatomic, retain)?尽管使用了(非原子,保留),为什么我必须保留属性?
【发布时间】: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


    【解决方案1】:

    您必须使用访问器:

    self.gameState = [NSMutableDictionary dictionaryWithContentsOfFile:sourcePath];
    

    或(等价于):

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

    而不是

    gameState = [NSMutableDictionary dictionaryWithContentsOfFile:sourcePath];
    

    它只设置 ivar 而没有任何属性的概念。

    【讨论】:

      【解决方案2】:

      您在哪里将 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 的严格规则,我不应该回答。祝你好运!

      【讨论】:

        猜你喜欢
        • 2012-03-06
        • 2012-03-18
        • 1970-01-01
        • 2011-12-30
        • 2011-07-06
        • 1970-01-01
        • 2014-07-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多