我正在关注一本关于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];
}
感谢毫无疑问会消失的光芒。)
答案 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];
}