Iphone 目标NSC可变字典内存管理

Iphone 目标NSC可变字典内存管理,iphone,objective-c,xcode,memory-management,Iphone,Objective C,Xcode,Memory Management,我有一个模型类,它保持由多个视图构建的跟踪记录。它有一个NSMutableDictionary,其中包含我最终写入数据库的字段和值。它会保存到plist,并在需要时重新加载。我以为我在跟踪我的记忆,但当我试图发布字典时,它抛出了一个EXC_BAD_访问。这是我的界面: #import <Foundation/Foundation.h> @interface CurrentEntryModel : NSObject { NSMutableDictionary *currentEn

我有一个模型类,它保持由多个视图构建的跟踪记录。它有一个NSMutableDictionary,其中包含我最终写入数据库的字段和值。它会保存到plist,并在需要时重新加载。我以为我在跟踪我的记忆,但当我试图发布字典时,它抛出了一个EXC_BAD_访问。这是我的界面:

#import <Foundation/Foundation.h>


@interface CurrentEntryModel : NSObject {
 NSMutableDictionary *currentEntry;
}

@property (nonatomic, retain) NSMutableDictionary *currentEntry;
- (void) setValue: (NSString *)value;
- (NSString *) getValue;

@end
如果我初始化这个类,它将自动创建字典,如果我调用set或get方法之一,字典似乎会被保留,因为它将正确地解除锁定。如果类刚刚初始化,然后没有调用任何方法,它将抛出EXC\u BAD\u访问错误。如果我没有弄错,当文件不存在时,我不会正确初始化字典,因为该方法以dictionary而不是init开头。虽然每次我运行这个程序时,文件都在那里,所以它总是使用文件查找逻辑,我认为这将保留变量

我没有正确初始化字典吗

编辑-更改方便方法上的代码以反映正确的方式。每个人都要注意斯奎吉要说的话。

这很糟糕

else {
        NSLog(@"file doesn't exist");
        currentEntry = [[NSMutableDictionary alloc ] dictionaryWithCapacity:1];
dictionaryWithCapacity:
NSMutableDictionary
上的一个类方法,它返回一个自动删除的对象,而您不
保留它。因此,run循环结束,字典自动删除。然后在
dealloc
中运行
[currentEntry release]
,它会爆炸,因为该对象已被解除分配

您可能不想使用容量:
初始化。始终将
alloc
与以
init
开头的方法配对


另外,当使用像这样的保留属性时,我通常让属性为我解决这个问题,并且只处理自动释放的对象。你只需要记住更少的规则,就会有更少的陷阱

- (id)init {
  // ...
  self.currentEntry = [NSMutableDictionary dictionWithContentsOfFile:file];
  // ...
}

- (void)dealloc {
  //...
  self.currentEntry = nil;
  //...
}
这样,您就不必直接在对象上调用
retain
release
。根据我的经验,这会减少令人困惑的bug。但这也是许多ObjC程序员的风格要点,并非所有人都同意。

Joshua-

+ (id)dictionaryWithCapacity:(NSUInteger)numItems
是NSDictionary的类方法。因此,当您调用它时,它应该是:

[NSMutableDictionary dictionaryWithCapacity:1];
不是:

此外,[NSMutableDictionary dictionaryWithCapacity:]返回自动删除的对象。如果希望将字典保持为ivar,而不是在运行循环的下一个周期中自动删除,则应调用:

[currentEntry retain];
因此,基本上,将其更改为:

currentEntry = [[NSMutableDictionary alloc] initWithCapacity:1];
或:


第一个可能更有意义,因为connivence类方法是为需要自动释放实例时使用而设计的。

是的,我今天发现了这一点,并在研究答案时在我的问题中引用了它。我读过的大多数教程都没有提到便利方法autorelease,您需要使用以init开头的方法。我确实改变了这一点,但它仍然抛出EXC_BAD_访问错误。根据内存管理规则:“正如你不应该关心对象的实际保留计数一样,你也不应该关心返回给你的对象是否自动释放。唯一关心的是,你是否拥有它。”假设返回给您的对象是否自动删除有点不利。特别是,
[NSNumber numberwhithint:0]
将为您提供一个您不拥有的对象,但通常也不会自动删除(它通常是缓存的)。这是一个很好的观点
init
retain
、或property assignment都表示“我拥有这个”。我编辑了问题以反映这一点,但它仍然没有回答问题。即使使用init方法,它仍然会抛出EXC\u BAD\u访问。我的理解是,这应该保留。不要假设从类方法返回的对象是否是“自动删除的”,相反,您应该只关心您是否拥有该对象。根据内存管理规则:“正如您不应该关心对象的实际保留计数一样,您也不应该关心返回给您的对象是否自动删除。唯一关心的是,您是否拥有它。”我很欣赏关于类方法的信息,但我在问题中已经指出,这不是错误的来源-
,尽管每次我运行它时,文件都在那里,因此它总是使用文件查找逻辑,我认为这将保留变量
。有人有什么想法吗?
[currentEntry retain];
currentEntry = [[NSMutableDictionary alloc] initWithCapacity:1];
currentEntry = [[NSMutableDictionary dictionaryWithCapacity:1] retain];