设置属性值时不必要的临时变量?

时间:2009-10-11 04:53:55

标签: iphone objective-c properties

我正在关注一本关于iPhone开发的书,我在示例代码中看到的特定模式对我来说没有多大意义。无论何时设置属性,它们首先为该属性的新值指定一个指针,然后将该属性设置为指针,然后释放指针。例如:

接口:

@interface DoubleComponentPickerViewController : UIViewController {
    NSArray *breadTypes;
}

@property(nonatomic, retain) NSArray *breadTypes;

@end

班级方法:

- (void)viewDidLoad {
    NSArray *breadArray = [[NSArray alloc] initWithObjects:@"White", @"Whole Wheat", @"Rye", @"Sourdough", @"Seven Grain", nil];
    self.breadTypes = breadArray;
    [breadArray release];
}

有没有理由这样做而不是仅仅执行以下操作?

- (void)viewDidLoad {
    self.breadTypes = [[NSArray alloc] initWithObjects:@"White", @"Whole Wheat", @"Rye", @"Sourdough", @"Seven Grain", nil];
}

感谢毫无疑问会消失的光芒。)

2 个答案:

答案 0 :(得分:9)

让我尝试以不同的方式解释它。

在其名称中包含alloc,copy或new的方法将为对象分配内存,并将该对象的所有权赋予调用者,并且调用者有责任释放该内存。

在viewDidLoad方法中,调用一个方法,该方法为您提供对象的所有权。发布它是您的方法的责任。但是,在你这样做之前,你想要用它来做一些事情 - 毕竟,这就是你分配它的原因,而不是仅仅发布它,而是用它做一些有用的事情。

无论你想用它做什么,你都必须释放它(或自动释放它*)。在这种情况下,您对该对象的使用是将其传递给self.breadTypes。 self.breadTypes可能看起来不像是一个方法,但它是(它是一个setter)。你传递breadArray。它做了它需要的东西。它可能会保留它以供以后使用,或者它可能会复制一些信息,或者复制整个事物。你的viewDidLoad并不在乎。它假设self.breadTypes做它需要的东西,当它返回时,它不关心你用breadArray做什么。

你用它做什么,就是你所拥有的任何东西 - 释放(或自动释放*)。

这就是你必须使用temp变量breadArray的原因。你不能完全从同一行的alloc中释放结果,因为对象会在self.breadTypes之前释放出来:

self.breadTypes = [[[NSArray alloc] initWithObjects:@"White", ..., nil] release];

因此,您被迫分配给临时变量,将其传递给self.breadTypes,然后释放breadArray中保存的对象。

现在,您可以尝试这样做,因此您不使用临时变量:

- (void)viewDidLoad {
    self.breadTypes = [[NSArray alloc] initWithObjects:@"White", @..., nil];
    [self.breadTypes release];
}

但这并不是非常有效,因为你正在调用另一个方法(self.breadTypes作为getter),如果你刚刚将值存储在temp变量中,那么你真的不需要这样做。

*现在,正如响应者所说,您可以使用autorelease作为替代版本:

- (void)viewDidLoad {
    self.breadTypes = [[[NSArray alloc] initWithObjects:@"White", ..., nil] 
                        autorelease];
}
Apple敦促我们三思而后行,是否要使用autorelease与release。自动释放可能不是每种情况的最佳选择。我个人喜欢尽快清理自己,不要不必使用autorelease。自动释放的对象在运行循环执行结束时释放,例如在viewDidLoad返回后不久。您应该阅读更多关于自动释放(以及iPhone上的内存管理,与MacOS X Cocoa略有不同),因为我过于简单化了。

顺便说一句:如果你retain一个对象,你就拥有它的所有权,并且在你完成它后,你将再次承担同样的责任。{/ 1}}。

答案 1 :(得分:3)

是。这些方法是分配变量,因此必须释放它们。该属性具有retain属性这一事实意味着,当您说@synthesize breadTypes;时,编译器实际上正在生成setBreadTypes,正确释放当前breadType成员并保留新成员。因此,您的函数不得保留变量alloc'ed。

你可以写下:

- (void)viewDidLoad {
    self.breadTypes = [[[NSArray alloc] initWithObjects:@"White",
                              @"Whole Wheat", @"Rye", @"Sourdough",
                              @"Seven Grain", nil] 
                        autorelease];
}

你想要了解Cocoa Memory Management