Iphone 在init中实例化NSDictionary/NSArray而无需额外保留的正确方法

Iphone 在init中实例化NSDictionary/NSArray而无需额外保留的正确方法,iphone,objective-c,memory-management,Iphone,Objective C,Memory Management,我有许多类使用各种NSDictionary/NSArray集合类作为IVAR,但我经常遇到这样的问题:我的集合类在包含类发布之前就被发布了 这似乎主要发生在集合类上,而不是另一个模型类(即我单独创建的类或其他NS*非集合类) 以下是我和其他人做过的两种变化: @实现类X // myDictionary declared as a property in the .h file as this: // @property (nonatomic, retain) NSMutableDictionar

我有许多类使用各种NSDictionary/NSArray集合类作为IVAR,但我经常遇到这样的问题:我的集合类在包含类发布之前就被发布了

这似乎主要发生在集合类上,而不是另一个模型类(即我单独创建的类或其他NS*非集合类)

以下是我和其他人做过的两种变化: @实现类X

// myDictionary declared as a property in the .h file as this:
// @property (nonatomic, retain) NSMutableDictionary *myDictionary;

@synthesize myDictionary;

- (id)int
{
    if (self = [super init])
    {
        // Option 1:
        // If I don't instantiate and assign with 'self',
        // myDictionary ivar will not be available 
        // at times in doSomething.

        myDictionary = [NSMutableDictionary dictionary];

        // Option 2:
        // Doing this, however will keep the dictionary around.
        // because I have invoked an extra retain on the dictionary
        self.myDictionary = [NSMutableDictionary dictionary];

        // Which one is more correct?   
    }
    return self;
}

- (void)doSomething
{
    // this will give the error about trying to invoke
    // a method on an already released instance
    [myDictionary objectForKey:@"myKey"];
}

- (void)dealloc
{
    // If I did self.myDictionary in 'init', I then
    // need to do this:
    [myDictionary release];
    [super dealloc];
}
@end

那么,哪种方法是在类中保存NSDictionary实例的更正确的方法呢?

选项2是正确的;选项1是错误的


但是您遗漏了最好的选项:
myDictionary=[[NSMutableDictionary alloc]init]
选项2是正确的;选项1是错误的


但是您遗漏了最好的选项:
myDictionary=[[NSMutableDictionary alloc]init]
我建议使用

myDictionary = [[NSMutableDictionary alloc] init];
如果调用[NSMutableDictionary],内存仅在您所在方法的范围内。一旦你离开这个方法,内存就会随之而去,这就是为什么如果你想保留这些值,你需要alloc/init

这就是为什么如果你没有遇到alloc,你不必释放

例如:

- (void) doSomething {

  // Do not need to release this string
  NSString *someText = @"Hello world!";

  // You need to release this string:
  NSString *otherText = [[NSString alloc] initWithString:@"Hello world!"];

  [otherText release];
}
编辑:在@mipadi@st3fan之后删除了self,发现了我的错误。忘了把零钱寄出去了。谢谢你让我负责。

我建议使用

myDictionary = [[NSMutableDictionary alloc] init];
如果调用[NSMutableDictionary],内存仅在您所在方法的范围内。一旦你离开这个方法,内存就会随之而去,这就是为什么如果你想保留这些值,你需要alloc/init

这就是为什么如果你没有遇到alloc,你不必释放

例如:

- (void) doSomething {

  // Do not need to release this string
  NSString *someText = @"Hello world!";

  // You need to release this string:
  NSString *otherText = [[NSString alloc] initWithString:@"Hello world!"];

  [otherText release];
}


编辑:在@mipadi@st3fan之后删除了self,发现了我的错误。忘了把零钱寄出去了。谢谢你让我负责。

为什么选项1错了?NSMutableDictionary类有一个静态初始值设定项方法,该方法返回一个空字典。@Justin,因为它是一个自动删除的字典,这意味着它将在运行循环的下一次旋转时消失,给ivar留下一个陈旧的指针。之后下次尝试访问它时,您将崩溃。
myDictionary=[[NSMutableDictionary]retain]很好。苹果在他们的@Pumbaa80中很好地解释了这一点:我认为编写
[[NSMutableDictionary]retain]
比使用我在回答中提到的标准alloc init版本没有任何好处。AFAIK唯一的区别是您的版本效率较低(它相当于
[[[NSMutableDictionary alloc]init]autorelease]retain]
)。关于编程指南的推荐很好,我完全同意。我只是想解释版本1是如何被“修复”的,因为我认为贾斯汀对此感到困惑。为什么选项1是错误的?NSMutableDictionary类有一个静态初始值设定项方法,该方法返回一个空字典。@Justin,因为它是一个自动删除的字典,这意味着它将在运行循环的下一次旋转时消失,给ivar留下一个陈旧的指针。之后下次尝试访问它时,您将崩溃。
myDictionary=[[NSMutableDictionary]retain]很好。苹果在他们的@Pumbaa80中很好地解释了这一点:我认为编写
[[NSMutableDictionary]retain]
比使用我在回答中提到的标准alloc init版本没有任何好处。AFAIK唯一的区别是您的版本效率较低(它相当于
[[[NSMutableDictionary alloc]init]autorelease]retain]
)。关于编程指南的推荐很好,我完全同意。我只是想解释一下第1版是如何“修复”的,因为我认为Justin对此感到困惑。如果
myDictionary
setter保留了它的参数,那么最终将导致内存泄漏。假设
myDictionary
是一个保留属性(为什么它不会是)。。。这是错误的建议,会泄漏内存。@mipadi@st3fan你们都错了。他直接设置ivar,而不是使用setter方法。@戴夫·德隆:检查编辑历史记录,答案以前确实使用过setter。你对
[NSDictionary dictionary]
如何管理内存的解释并不准确。您可以安全地从方法返回自动删除的词典。它至少会一直存在,直到它的自动释放池耗尽为止。如果
myDictionary
setter保留了它的参数,那么最终将导致内存泄漏。假设
myDictionary
是一个保留属性(为什么不是)。。。这是错误的建议,会泄漏内存。@mipadi@st3fan你们都错了。他直接设置ivar,而不是使用setter方法。@戴夫·德隆:检查编辑历史记录,答案以前确实使用过setter。你对
[NSDictionary dictionary]
如何管理内存的解释并不准确。您可以安全地从方法返回自动删除的词典。它至少会一直存在,直到它的自动释放池被排干。