乍一看,您的示例似乎可行,但实际上它会造成内存泄漏。
按照 Cocoa 和 Cocoa-touch 中的约定,使用 [[SomeClass alloc] initX] 或 [SomeClass newX] 创建的任何对象的保留计数为 1。当您完成新实例时,您有责任调用 [someClassInstance release],通常是在您的 dealloc 方法中。
当您将新对象分配给属性而不是实例变量时,这会变得棘手。大多数属性被定义为retain 或copy,这意味着它们要么在设置时增加对象的保留计数,要么复制对象,而原始对象保持不变。
在您的示例中,您的 .h 文件中可能有这个:
@property (retain) EditingViewController *editingViewController;
所以在你的第一个例子中:
EditingViewController *controller =
[[EditingViewController alloc] initWithNibName:@"EditingView" bundle:nil];
// (1) new object created with retain count of 1
self.editingViewController = controller;
// (2) equivalent to [self setEditingViewController: controller];
// increments retain count to 2
[controller release];
// (3) decrements retain count to 1
但是对于你的第二个例子:
// (2) property setter increments retain count to 2
self.editingViewController =
// (1) new object created with retain count of 1
[[EditingViewController alloc] initWithNibName:@"EditingView" bundle:nil];
// oops! retain count is now 2
通过在将新对象传递给 setter 之前在新对象上调用 autorelease 方法,您可以请求自动释放池获取该对象的所有权并在未来某个时间释放它,因此有一段时间该对象有两个所有者匹配它的保留计数,一切都是 hunky dory。
// (3) property setter increments retain count to 2
self.editingViewController =
// (1) new object created with retain count of 1
[[[EditingViewController alloc] initWithNibName:@"EditingView" bundle:nil]
// (2) give ownership to autorelease pool
autorelease];
// okay, retain count is 2 with 2 owners (self and autorelease pool)
另一种选择是将新对象直接分配给实例变量而不是属性设置器。假设您的代码将底层实例变量命名为editingViewController:
// (2) assignment to an instance variable doesn't change retain count
editingViewController =
// (1) new object created with retain count of 1
[[EditingViewController alloc] initWithNibName:@"EditingView" bundle:nil];
// yay! retain count is 1
这是代码中一个微妙但关键的区别。在这些示例中,self.editingViewController = x 是 [self setEditingViewController: x] 的语法糖,但 editingViewController 是一个普通的旧实例变量,没有任何由编译器生成的保留或复制代码。
另见Why does this create a memory leak (iPhone)?