我正在为我的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的,我想自己管理内存,所以我选择不使用自动释放池(它还具有更好的性能和更低的最大内存使用率)。
我知道这个模式有效(并且已经在几个SO帖子中进行了讨论):
NSNumber *num = [[NSNumber alloc] initWithInteger:1];
thing.number = num;
[num release];
这种模式非常清楚,但我对这三行或临时变量并不感到兴奋。
我认为这也会有效(但我没有在任何SO帖子上注意到它):
thing.number = [[NSNumber alloc] initWithInteger:1];
[thing.number release];
此模式不太清楚,但只需要两行而不使用临时变量。
问题
是否有其他模式可以将新对象分配给保留属性(不使用自动释放池)?这里的最佳做法是什么?
答案 0 :(得分:3)
除了使用自动释放池之外,这些是我所见过的唯一一个。我不会太警惕自动释放。它们工作正常,这种情况下你可能看不到任何性能差异。
但是,如果您真的想避免这种情况,那么这里适用的最佳做法似乎是“最少惊喜原则”。由于在大多数示例代码中都找到了第一个习惯用法,因此为了维护代码的人,你似乎应该只是为了获取额外的行。
答案 1 :(得分:2)
无论您是否使用它们,默认情况下自动释放池已经包围您的代码。就个人而言,如果你不使用自动释放的对象,我认为你不会获得更好的性能。请记住,自动释放池和垃圾收集是两个不同的概念,前者更简单。您不想使用自动释放对象的唯一地方是大循环。
为了记录,第二种模式应该也可以正常工作。
答案 2 :(得分:1)
自动释放池不应该使用明显更多的内存,除非您在紧密循环中创建了大量对象。
我猜您的选择是要么需要使用您需要编写的2行或3行代码,要么只使用自动释放池。
就个人而言,除非遇到特定的性能或内存问题,否则我肯定会使用自动释放池。
答案 3 :(得分:1)
对于许多对象,您可以直接使用返回自动释放实例的方法。例如,我通常会编写相应的代码片段,如下所示:
thing.number = [NSNumber numberWithInt:1];
请注意,由于您的属性保留了NSNumber,因此您需要在完成该属性后稍后将其释放。
无论如何,如果这不适用,因为你没有构造函数返回自动释放的对象,那么你的模式1肯定是正确的。
相反,模式2在我看来是错误的,原因如下:首先将NSNumber分配给您的属性,然后释放您的属性。但是,您需要释放已分配的NSNumber,而不是您的属性保留的NSNumber(稍后您将在完成该属性后再次执行此操作)。模式2的净效应应该是内存泄漏(分配的NSNumber未释放)和您的属性不包含NSNumber(因为您首先保留它然后释放它)。