我看到很多代码,特别是苹果示例代码,类似于以下代码:
EditingViewController *controller = [[EditingViewController alloc] initWithNibName:@"EditingView" bundle:nil];
self.editingViewController = controller;
[controller release];
是否有任何理由特别证明上述方法有利于:
self.editingViewController = [[EditingViewController alloc] initWithNibName:@"EditingView" bundle:nil];
试图了解是否有上述策略。
谢谢!
最佳答案
乍一看,您的示例似乎可以工作,但实际上它会造成内存泄漏。
根据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
方法,可以要求autorelease池取得该对象的所有权,并在将来的某个时间释放它,因此在一段时间内,该对象有两个所有者来匹配其保留计数,并且一切都非常棒。// (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)?