为什么人们总是对 Objective-C(即 iPhone)中的实例变量使用重新赋值?

Why do people always use reassignment for instance variables in Objective-C (namely iPhone)?

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

1
someInstanceVar = [[Classname alloc] init];

他们总是去

1
2
3
Classname *tempVar = [[Classname alloc] init];
someInstanceVar = tempVar;
[tempVar release];

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


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

详情:

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

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

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

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

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

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

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

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

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

  • 之前存储在 propertyVar 中的任何值都会被释放
  • 新值被保留或复制
  • 自动处理任何副作用(例如 KVC/KVO 通知)