【问题标题】:OBJ-C: How to release object which is return from method?OBJ-C:如何释放从方法返回的对象?
【发布时间】:2013-04-04 05:53:02
【问题描述】:

我对从方法返回的对象的内存警告感到困惑。 这是我的代码。

-(void)returnHeaderView
{
  self.headerView=[[UIView alloc]init];
  headerView.frame=CGRectMake(0, 0, 955, 45);


  UILabel *fromLabel=[self returnLabel];
  fromLabel.frame=CGRectMake(400, 5, 200, 44);
  fromLabel.text=@"Open Time";
  [headerView addSubview:fromLabel];
  [fromLabel release];(in correct decrement of the reference count of an object that is not owned at this point by the caller)

 [self.headerView addSubview:fromLabel];
 [self.view addSubview:self.headerView];
 [self.headerView release];

}

-(UILabel *)returnLabel
{
UILabel *label= [[UILabel alloc] init] ;
label.textColor = [UIColor blackColor];
label.font = FONT_TITLE;
label.numberOfLines=1;
label.textAlignment=UITextAlignmentLeft;
label.lineBreakMode=UILineBreakModeWordWrap;
label.backgroundColor=[UIColor clearColor];

return label;

}

这是我的两种方法。 1.-(void)returnHeaderView。 2.-(UILabel *)returnLabel.

-returnLabel 是返回标签,方法返回的 UILabel 对象的引用传递给 returnHeaderView 方法的 fromLabel UILabel 对象。 然后我释放 fromLabel 对象。

但它给出了内存警告( 正确减少调用者此时不拥有的对象的引用计数)。

所以有人建议我这段代码有什么问题。 以及如何释放方法返回的对象。

谢谢。

【问题讨论】:

标签: ios objective-c memory-leaks


【解决方案1】:

在您的returnHeaderView 中,您实际上并没有保留fromLabel,因此您不拥有它,也不应该在那里释放它(警告“不正确地减少不属于的对象的引用计数调用者的这一点”)。

最好的选择是自动释放返回的标签:return [label autorelease];,让它一直存在,直到周围的自动释放池被耗尽。请注意,这也意味着从您的 returnHeaderView 方法中删除 [fromLabel release]; 调用。

如果这听起来很复杂,请按照实际推荐的方式使用 ARC。

【讨论】:

    【解决方案2】:

    请进行小改动并删除泄漏并自动释放 self.headerView 以删除其他内存泄漏警告:

    -(void)returnHeaderView
    {
      self.headerView=[[[UIView alloc]init] autorelease];
      headerView.frame=CGRectMake(0, 0, 955, 45);
    
      UILabel *fromLabel = [[self returnLabel] retain];
      fromLabel.frame    = CGRectMake(400, 5, 200, 44);
      fromLabel.text     = @"Open Time";
      [headerView addSubview:fromLabel];
      [self.headerView addSubview:fromLabel];
      [self.view addSubview:self.headerView];
      //[self.headerView release];
    }
    
    -(UILabel *)returnLabel
    {
      UILabel *label= [[UILabel alloc] init] ;
      label.textColor = [UIColor blackColor];
      label.font = FONT_TITLE;
      label.numberOfLines=1;
      label.textAlignment=UITextAlignmentLeft;
      label.lineBreakMode=UILineBreakModeWordWrap;
      label.backgroundColor=[UIColor clearColor];
      return [label autorelease];
    }
    

    【讨论】:

      【解决方案3】:

      在我看来,您的 returnLabel 方法返回了一个保留计数为 1 的对象,而不是编译器建议的零。我认为您可能只需要更改方法名称即可向编译器提示返回对象的所有权。尝试将returnLabel 更改为createReturnLabel。那么该方法将符合copy/create naming convention

      【讨论】:

        【解决方案4】:

        您可以通过更改代码来避免泄漏:

        -(void)returnHeaderView
        {
          self.headerView=[[UIView alloc]init];
          headerView.frame=CGRectMake(0, 0, 955, 45);
        
        
          UILabel *fromLabel = [[self returnLabel] retain];
          fromLabel.frame    = CGRectMake(400, 5, 200, 44);
          fromLabel.text     = @"Open Time";
          [headerView addSubview:fromLabel];
          [self.headerView addSubview:fromLabel];
          [self.view addSubview:self.headerView];
        
          [fromLabel release];
          [self.headerView release];
        
        }
        
        -(UILabel *)returnLabel
        {
        UILabel *label= [[UILabel alloc] init] ;
        label.textColor = [UIColor blackColor];
        label.font = FONT_TITLE;
        label.numberOfLines=1;
        label.textAlignment=UITextAlignmentLeft;
        label.lineBreakMode=UILineBreakModeWordWrap;
        label.backgroundColor=[UIColor clearColor];
        
        return [label autorelease];
        
        }
        

        建议:避免此类泄漏的最佳方法是使用 ARC。

        【讨论】:

        • 如果他将自动释放添加到returnLabel,他甚至不需要保留和释放。如果他这样做,他应该只添加自动释放,这样 returnLabel 返回一个自动释放的对象,然后在returnHeaderView 中不保留或释放fromLabel
        • @AaronGolden:他正在对返回的UILabel 执行一些任务。因此,如果 autorelease pool 在 return 语句后立即耗尽,则可能会发生崩溃。
        • 但在returnLabel 在 OP 发布的代码中返回后,自动释放池肯定不会立即耗尽!
        • @AaronGolden:是的,没关系。但这不是推荐的方式。始终保留返回的自动释放对象(获取所有权)。 Apple 文档推荐这种方法。
        • fromLabel 由self.headerView 保留在[self.headerView addSubview:fromLabel] 中。绝对没有理由在此处包含额外的保留和释放。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-18
        • 1970-01-01
        • 1970-01-01
        • 2011-06-23
        • 1970-01-01
        • 2016-01-21
        相关资源
        最近更新 更多