10

我总是在 viewDidLoad 方法中看到示例代码,而不是说,例如

someInstanceVar = [[Classname alloc] init];

他们总是去

Classname *tempVar = [[Classname alloc] init];
someInstanceVar = tempVar;
[tempVar release];

为什么是这样?不是完全一样,只是更长吗?

4

1 回答 1

12

简短的回答:这种模式一直出现在 iPhone 代码中,因为它被认为是创建新对象并将其分配给成员变量的最佳方式,同时仍然尊重所有内存管理规则并调用适当的副作用(如果任何)同时也避免使用自动释放。

细节:

您的第二个示例将创建一个僵尸,因为var它持有一个指向已释放内存的指针。一个更可能的用例如下所示:

tempVar = [[Classname alloc] init];
self.propertyVar = tempVar;
[tempVar release];

假设这propertyVar是一个声明为copyretain属性,此代码将新对象的所有权移交给该类。

更新 1:以下代码是等效的,但在 iOS 上不推荐*,这可能是大多数 iPhone 程序使用第一种模式的原因。

self.propertyVar = [[[Classname alloc] init] autorelease];

*在 iOS 上不鼓励使用autorelease ,因为过度使用它会导致问题。确保您永远不会过度使用它的最简单方法是永远不要全部使用它,因此您会经常看到使用alloc/initand的 iOS 代码release,即使在autorelease可以接受的情况下也是如此。这是编码器偏好的问题。

更新 2:由于 Cocoa 在幕后自动执行的内存管理,这种模式起初看起来令人困惑。这一切的关键是用于设置成员变量的点表示法。为了帮助说明,请考虑以下两行代码是相同的:

self.propertyVar = value;
[self setPropertyVar:value];

当您使用点表示法时,Cocoa 将为指定的成员变量调用属性访问器。如果该属性被定义为copyorretain属性(这是该模式在不创建僵尸的情况下工作的唯一方法),那么会发生几件非常重要的事情:

  1. 之前存储的任何值都会被propertyVar释放
  2. 新值被保留或复制
  3. 自动处理任何副作用(例如 KVC/KVO 通知)
于 2010-09-27T18:37:18.877 回答