为指针/内存管理可可战略


4

我看到很多代码,特别是在苹果的示例代码,类似于以下内容:

EditingViewController *controller = [[EditingViewController alloc] initWithNibName:@"EditingView" bundle:nil]; 
    self.editingViewController = controller; 
    [controller release]; 

有什么理由特别是接近上述过证明是有益的:

self.editingViewController = [[EditingViewController alloc] initWithNibName:@"EditingView" bundle:nil]; 

试图了解是否有上述策略。

谢谢!

8

乍一看,您的示例似乎可以工作,但实际上它会产生内存泄漏。

按照可可和Cocoa-touch中的惯例,使用[[SomeClass alloc] initX][SomeClass newX]创建的任何对象都创建时保留数为1。当您完成新实例时,您有责任拨打[someClassInstance release],通常使用您的dealloc方法。

这很棘手的地方是当你将新的对象分配给属性而不是实例变量。大多数属性定义为retaincopy,这意味着它们可以在设置时递增对象的保留计数,也可以创建对象的副本,而不改变原始属性。

在你的榜样,你可能有这样的在你的.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方法,然后将其传递给你要求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)?

  0

@property(retain)EditingViewController * editingViewController; (2)属性设置器增量保留计数为2 self.editingViewController = //(1)使用保留计数为1创建的新对象 [[EditingViewController alloc] initWithNibName:@“EditingView”bundle:nil]; //哎呀!保留计数现在是2 这是不正确的。编译器创建的setter方法将释放作为参数传递的对象,并保留该属性。因此,保留计数为1并且没有问题。 03 3月. 112011-03-03 00:33:37


4

你可以写:

self.editingViewController = [[[EditingViewController alloc] initWithNibName:@"EditingView" bundle:nil] autorelease]; 

而且我经常在非速度关键领域做。问题是该属性很可能是“保留”属性,这意味着如果你不释放它,对象将被泄漏。

应该注意的是,autorelease比release更昂贵,但我更喜欢简洁的代码,以提高纯文本的可读性。

  0

即使它是复制属性,你会泄漏。 22 2月. 092009-02-22 09:31:57

  0

我想你错过了最后的autorelease调用。 06 3月. 092009-03-06 01:00:39