【问题标题】:Objects creation and instantiation in objective-cObjective-c 中的对象创建和实例化
【发布时间】:2011-07-06 12:24:59
【问题描述】:
鉴于下面的一段代码,其中 blueViewController 是 iVar。
问题:为什么不直接实例化 iVar?
BlueViewController *blueController = [[BlueViewController alloc]initWithNibName:@"BlueView" bundle:nil];
self.blueViewController = blueController;
[blueController release];
【问题讨论】:
标签:
objective-c
memory-management
【解决方案1】:
这取决于你在课堂上的位置。如果您在 init(和 dealloc)方法中,建议直接引用 ivar 以避免 setter 逻辑中的任何副作用。因此在初始化时我会这样做
_blueViewController = [[BlueViewController alloc] initWithNibName:@"BlueView" bundle:nil];
但是在其他任何地方我都会按照你的做法去做。然后,如果 getter/setter 中有任何自定义逻辑,我知道它会运行。
为了阐述@Vladimar 的观点,retain 的综合设置器将执行一些类似于此的内存管理:
- (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】:
您可以直接初始化 iVar,但您拥有的代码还可以处理先前 blueViewController 值的内存管理。直接访问 iVar,您必须在分配新值之前手动释放先前的值。
【解决方案3】:
如果您愿意,您可以在一条线上完成所有操作。重要的是平衡 +alloc 与 -release 或 -autorelease。所以,你可以说:
self.blueViewController = [[[BlueViewController alloc] initWithNibName:@"BlueView" bundle:nil] autorelease];
这很好,但有些人更喜欢避免 -autorelease,而有些人只是更喜欢更简单的步骤和/或更短的代码行。在这方面使用您所做的中间变量会有所帮助,而且不会花费任何成本。
【解决方案4】:
这取决于属性是否为retain。大多数对象属性被保留;这是一个保留属性的样子:
- (void)setBlueViewController:(BlueViewController *)bvc {
if (bvc != blueViewController) { // blueViewController is local ivar
[blueViewController release];
blueViewController = [bvc retain];
}
}
因此,您在那里所做的是创建 +2 的保留计数。当您init 时,这是+1;该物业然后retains ,将其提升至+2。你的dealloc 释放一次,这使它降到+1……你已经泄露了该属性。因为您是alloc/init-ing 变量,所以您不想使用setter;相反,将其直接分配给实例变量。
通过直接实例化它,它为您省去了其他release 的麻烦——更少的代码行意味着更少的错误。例如,您可能无意中输入了retain,直到您的程序崩溃时才意识到它,因为您保留了一个庞大的类...
当然,正如 Caleb 所说,您可以自动释放,但这实际上是让对象在内存中闲置,直到运行循环完成。它更容易,并且给你更多的控制,只是不用担心。将alloc/init 分配给 ivar 没有任何问题;事实上,这是最好的方法。