我看到很多代码,特别是在Apple示例代码中,类似于以下内容:
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
通过autorelease
在将新对象传递给setter之前调用该对象的方法,您要求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)
另一种选择是将新对象直接分配给实例变量而不是属性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
是一个普通的旧实例变量,没有编译器生成的任何保留或复制代码.
另请参阅为什么会造成内存泄漏(iPhone)?