1

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

例如,“事物”实体中的“数字”属性:

#import <CoreData/CoreData.h>

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

@implementation Thing 
@dynamic number;
@end

在我的代码中使用 Thing 对象时,我一直在设置 number 属性,如下所示:

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];
    

    这种模式不太清楚,但只需要两行并且不使用临时变量。

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

4

4 回答 4

3

除了使用自动释放池之外,这些是我唯一见过的。我不会对自动释放过于警惕。它们工作得很好,在这种情况下您可能看不到任何性能差异。

但是,如果您真的想避免这种情况,这里适用的最佳实践似乎是“最小意外原则”。由于第一个习语在大多数示例代码中都可以找到,看起来你应该为了维护代码的人而吸收额外的行。

于 2009-11-12T07:18:33.660 回答
2

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

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

于 2009-11-12T07:16:42.883 回答
1

除非您在紧密循环中创建大量对象,否则自动释放池不应使用更​​多内存。

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

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

于 2009-11-12T07:16:08.637 回答
1

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

thing.number = [NSNumber numberWithInt:1];

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

无论如何,当这不适用时,因为您没有构造函数返回自动释放的对象,您的模式 1 绝对是正确的。

相反,在我看来,模式 2 不正确,原因如下:您首先将 NSNumber 分配给您的财产,然后释放您的财产。但是,您需要释放您分配的 NSNumber,而不是您的财产保留的那个(稍后您将这样做,当您完成财产时再次这样做)。模式 2 的最终结果应该是内存泄漏(分配的 NSNumber 未释放)并且您的属性不包含 NSNumber(因为您首先保留它然后释放它)。

于 2009-11-12T09:01:06.787 回答