我看到很多代码,特别是在Apple示例代码中,类似于以下内容:
EditingViewController *controller = [[EditingViewController alloc] initWithNibName:@"EditingView" bundle:nil];
self.editingViewController = controller;
[controller release];
特别是有任何理由认为上述方法对以下方法有益:
self.editingViewController = [[EditingViewController alloc] initWithNibName:@"EditingView" bundle:nil];
试图了解是否有上述策略。
谢谢!
答案 0 :(得分:8)
乍一看,您的示例似乎可以正常工作,但事实上它会造成内存泄漏。
按照惯例,在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)
另一种选择是将新对象直接分配给实例变量而不是属性setter。假设您的代码命名为基础实例变量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
是一个普通的旧实例变量,没有编译器生成的任何保留或复制代码。
答案 1 :(得分:4)
你可以写:
self.editingViewController = [[[EditingViewController alloc] initWithNibName:@"EditingView" bundle:nil] autorelease];
我经常在非速度关键领域做。问题是该属性很可能是一个“保留”属性,这意味着如果你不释放它,该对象将被泄露。
应该注意的是,自动释放比发布更昂贵,但我也更喜欢简洁的代码,以提高纯度的可读性。