【问题标题】:UIButton retain counter increase after touchUIButton在触摸后保留计数器增加
【发布时间】:2011-09-14 21:35:17
【问题描述】:

我创建了一组相同的自定义类型的对象。所有对象都有方法showDeleteButtonhideDeleteButton。 我发现当我隐藏删除按钮(删除它)时按下的按钮有retainCounter == 2。

代码如下:

-(void)showDeleteButton {
if(!isDeleteButtonLoaded) { // Check that method was't triggered twice
    UIButton *aDeleteButton = [[UIButton alloc] initWithFrame:CGRectMake(-3, -7, 30, 29)]; // RC == 1
    [aDeleteButton setImage:[UIImage imageNamed:@"close_button.png"] forState:UIControlStateNormal];
    [self addSubview:aDeleteButton]; // RC == 2
    [aDeleteButton addTarget:self action:@selector(deleteButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
    deleteButton = aDeleteButton;
    [aDeleteButton release]; // RC == 1
    isDeleteButtonLoaded = YES;
    NSLog(@"delete button retain count (created): %d", [deleteButton retainCount]);
    [self setNeedsDisplay];
}

}

-(void)deleteButtonPressed:(id)sender {
[delegate deleteImageAtPath:self.imageFullPath];

}

-(void)hideDeleteButton {
if(isDeleteButtonLoaded) {
    NSLog(@"delete button retain count (before): %d", [deleteButton retainCount]); // RC == 1
    [deleteButton removeFromSuperview]; // RC == 0
    deleteButton = nil;
    isDeleteButtonLoaded = NO;
    [self setNeedsDisplay];
}

}

所以对于第二种方法中的按下按钮 NSLog 显示 RC == 2!有任何想法吗?我 100% 确定不能从课堂外访问 deleteButton。

【问题讨论】:

  • 我会添加一些解释。视图包含添加到 UIScrollView 的那些方法。在我显示删除按钮后,按下它并隐藏它我注意到在 UISrollView 中出现了另一个子视图 - UIImageView。我确定我不会手动添加它。我检查了几次。没有 addSubview: 调用。所以我只是认为它可能是来自 deleteButton 的一些缓存数据...
  • 所以层次结构是: UIScrollView 有 3 MyCustomView (上面提到的方法)。 MyCustomVew 具有“可选”子视图 deleteButton。在 UIScrollView 中加载 deleteButton 后,又出现了一个带有 UIImageView 类的子视图。我试图找出原因。

标签: objective-c ios memory-management memory-leaks retaincount


【解决方案1】:

不要看 RETAINCOUNT

咳咳

retainCount 对任何理智的人来说都是没有意义的,只要你遵循记忆规则,一切都会好起来的。

【讨论】:

  • 想不出更好的答案:)
  • 您是否有任何迹象表明您正在泄漏按钮?如果没有,那么你没有问题。
【解决方案2】:

切勿查看retainCounts 以获取任何有用信息。在 Apple 的内部框架中,他们可能随时对您的对象调用保留或释放。您需要担心的是您的保留(或分配,或复制)和释放语句是否正确匹配。添加一个视图作为另一个视图的子视图(或将其添加到任何 NSArray)也会增加它的 retainCount...不过你不必担心。

【讨论】:

    【解决方案3】:

    查看 stackoverflow popular question,了解为什么从不使用 retainCount 而是使用 Apple 工具来跟踪内存泄漏。

    【讨论】:

      【解决方案4】:

      永远不要使用retainCount。结果充其量是误导性的。

      第一件事,去阅读Apple's memory management guidelines

      其次,使用这些指南来修复代码中的一些内存问题:

      UIButton *aDeleteButton = [[UIButton alloc] initWithFrame:CGRectMake(-3, -7, 30, 29)];
      // Retain count +1
      // Some code...
      deleteButton = aDeleteButton;
      [aDeleteButton release];
      // Retain count -1
      

      你分配一个新的UIButton 然后你释放它。这意味着该按钮不归您所有,并且可能随时消失。我猜您的班级中有一个名为deleteButton 的属性?如果是这样,请像这样使用它:self.deleteButton = aDeleteButton;

      在您的 hideDeleteButton 方法中,您可能想要使用如下所示的内容:

      [self.deleteButton removeFromSuperview];
      self.deleteButton = nil;
      isDeleteButtonLoaded = NO;
      [self setNeedsDisplay];
      

      再次假设您的类中有一个名为deleteButton 的属性。如果您没有,请制作一个并使用它。它极大地简化了内存管理任务。

      【讨论】:

      • 我的代码 AFAIK 没有问题。 [self addSubview:aDeleteButton] 增加保留计数器,这在文档中有所提及。
      • 为什么它假定我有一个属性顺便说一句?我的代码中没有 self.xxx 语法。我只使用班级成员deleteButton。我想我不需要为这种简单的情况创建属性......
      • 没有问题,因为您要么 A) 幸运,要么 B) 在编写代码时非常擅长跟踪对象的保留/释放。您的 deleteButton ivar 取决于 self.view 的状态以保持有效。这是一个让自己陷入脆弱的境地,没有理由这样做。如果你想保留对deleteButton 的引用,你应该保留自己。
      • 你不需要创建一个属性,但如果你不需要,你应该练习适当的内存管理。 Retain 对象,如果你想持有对它们的引用,release 对象当你完成时。
      • 是的 deleteButton 取决于其父视图的状态(在本例中为自身)。如果我要发布superview,它将发布deleteButton。恕我直言,这很合乎逻辑......无论如何谢谢:)
      猜你喜欢
      • 2014-09-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-10
      • 2010-12-19
      • 1970-01-01
      • 1970-01-01
      • 2011-11-10
      相关资源
      最近更新 更多