将新对象分配给保留属性的最佳实践?

时间:2009-11-12 07:04:07

标签: iphone memory-management core-data properties cocoa-design-patterns

我正在为我的iPhone应用程序使用Core Data。我的属性使用保留属性设置。

例如,“Thing”实体中的“number”属性:

#import <CoreData/CoreData.h>

@interface Thing :  NSManagedObject  
{
}
@property (nonatomic, retain) NSNumber * number;
@end

@implementation Thing 
@dynamic number;
@end

在代码中使用Thing对象时,我一直在设置数字属性:

thing.number = [[NSNumber alloc] initWithInteger:1];

但是,这会产生内存泄漏(由于alloc plus属性保留,新的NSNumber对象的保留计数比期望的高一个)。

由于这是针对iPhone OS的,我想自己管理内存,所以我选择不使用自动释放池(它还具有更好的性能和更低的最大内存使用率)。

  1. 我知道这个模式有效(并且已经在几个SO帖子中进行了讨论):

    NSNumber *num = [[NSNumber alloc] initWithInteger:1];
    thing.number = num;
    [num release];
    

    这种模式非常清楚,但我对这三行或临时变量并不感到兴奋。

  2. 我认为这也会有效(但我没有在任何SO帖子上注意到它):

     thing.number = [[NSNumber alloc] initWithInteger:1];
     [thing.number release];
    

    此模式不太清楚,但只需要两行而不使用临时变量。

  3. 问题
    是否有其他模式可以将新对象分配给保留属性(不使用自动释放池)?这里的最佳做法是什么?

4 个答案:

答案 0 :(得分:3)

除了使用自动释放池之外,这些是我所见过的唯一一个。我不会警惕自动释放。它们工作正常,这种情况下你可能看不到任何性能差异。

但是,如果您真的想避免这种情况,那么这里适用的最佳做法似乎是“最少惊喜原则”。由于在大多数示例代码中都找到了第一个习惯用法,因此为了维护代码的人,你似乎应该只是为了获取额外的行。

答案 1 :(得分:2)

无论您是否使用它们,默认情况下自动释放池已经包围您的代码。就个人而言,如果你不使用自动释放的对象,我认为你不会获得更好的性能。请记住,自动释放池和垃圾收集是两个不同的概念,前者更简单。您不想使用自动释放对象的唯一地方是大循环。

为了记录,第二种模式应该也可以正常工作。

答案 2 :(得分:1)

自动释放池不应该使用明显更多的内存,除非您在紧密循环中创建了大量对象。

我猜您的选择是要么需要使用您需要编写的2行或3行代码,要么只使用自动释放池。

就个人而言,除非遇到特定的性能或内存问题,否则我肯定会使用自动释放池。

答案 3 :(得分:1)

对于许多对象,您可以直接使用返回自动释放实例的方法。例如,我通常会编写相应的代码片段,如下所示:

thing.number = [NSNumber numberWithInt:1];

请注意,由于您的属性保留了NSNumber,因此您需要在完成该属性后稍后将其释放。

无论如何,如果这不适用,因为你没有构造函数返回自动释放的对象,那么你的模式1肯定是正确的。

相反,模式2在我看来是错误的,原因如下:首先将NSNumber分配给您的属性,然后释放您的属性。但是,您需要释放已分配的NSNumber,而不是您的属性保留的NSNumber(稍后您将在完成该属性后再次执行此操作)。模式2的净效应应该是内存泄漏(分配的NSNumber未释放)和您的属性不包含NSNumber(因为您首先保留它然后释放它)。