给出下面的代码,其中blueViewController是一个iVar 问题:为什么不直接实例化iVar?
BlueViewController *blueController = [[BlueViewController alloc]initWithNibName:@"BlueView" bundle:nil];
self.blueViewController = blueController;
[blueController release];
答案 0 :(得分:2)
您可以直接初始化iVar,但您所拥有的代码也会处理以前的blueViewController值的内存管理。直接访问iVar,您必须在分配新值之前手动释放以前的值。
答案 1 :(得分:2)
这取决于你班上的位置。如果您使用的是init(和dealloc)方法,建议直接引用ivar以避免在setter逻辑中出现任何副作用。因此在init中我会做
_blueViewController = [[BlueViewController alloc] initWithNibName:@"BlueView" bundle:nil];
但是在其他任何地方我都会这样做你怎么做的。然后,如果getter / setter中有任何自定义逻辑,我知道它将被运行。
要详细说明@ Vladimar的观点,保留的合成setter将执行类似于此的一些内存管理:
- (void)setMyObject:(MyObject *)newMyObject
{
// If it's the same object we don't need to do anything
if (_myObject != newMyObject) {
[newMyObject retain];
[_myObject release];
_myObject = newMyObject;
}
}
当你设置你的ivars时,让getter / setter担心所有这些逻辑会更安全。
答案 2 :(得分:1)
如果需要,您可以在一行中完成所有操作。重要的是平衡+ alloc与-release或-autorelease。所以,你可以说:
self.blueViewController = [[[BlueViewController alloc] initWithNibName:@"BlueView" bundle:nil] autorelease];
这很好,但是有些人更喜欢避免-autorelease,而有些人更喜欢简单的步骤和/或更短的代码行。在这方面使用中间变量有助于这方面,而且不需要任何费用。
答案 3 :(得分:1)
取决于属性是否为retain
。保留了大多数对象属性;这就是保留属性的样子:
- (void)setBlueViewController:(BlueViewController *)bvc {
if (bvc != blueViewController) { // blueViewController is local ivar
[blueViewController release];
blueViewController = [bvc retain];
}
}
所以你在那里做的是创建一个+2的保留计数。当你init
时,那是+1;该属性然后retain
s,将其提升到+2。你的dealloc
发布一次,将其降低到+1 ......你就泄露了这个属性。因为你是变量的alloc
/ init
,所以你不想使用setter;相反,将其直接分配给实例变量。
通过直接实例化,可以省去其他release
的麻烦 - 更少的代码行意味着更少的错误。例如,您可能偶然输入了retain
并且在您的程序崩溃之前没有实现它,因为您保留了一个庞大的类......
当然,正如Caleb所说,你可以自动释放,但这有效地让对象在内存中存在,直到运行循环结束。它更容易,并为您提供更多控制,只是不用担心。将alloc
/ init
分配给ivar并没有错;事实上,这是最好的方法。