消息发送到解除分配的实例

时间:2011-01-27 14:28:31

标签: objective-c memory-management

使用Objective-c相当新,但到目前为止设法从头开始创建一个卡片应用程序。 游戏的想法是与电脑进行纸牌游戏。

在函数updatePlayerCardView中,我获得了玩家拥有的一组牌,并在屏幕上放置了具有组名的按钮。 这样可以正常工作一次,但是当第二次调用该函数时,它会失败:

- [CFString retain]:发送到解除分配的实例0x604ac60的消息

经过一些调试和研究后,我发现发生这种情况的一行是:

[cardButton setTitle:[NSString stringWithFormat:@“%@(%i)”,[group groupName],[player getCardGroupCount:group]] forState:UIControlStateNormal];

所以NSString被解除分配明显,我不明白的是;应该重新创建所有按钮,为什么我有一个解除分配的实例? 有没有更好的方法来每次更新播放器视图。从一开始就不知道按钮的数量。

-(void)updatePlayerCardView { 

 NSMutableArray *groups = [[[game players] objectAtIndex:0] getCardGroups];
 Player *player = [game getPlayer:0];
 int x = 13;
 int y = 157;

 for(int i = 0; i < [groups count]; i++) {
     QuartetGroup *group = [groups objectAtIndex:i];
     int cardGroupCount = [player getCardGroupCount:group];

     if(cardGroupCount == [[game quartet] getCardsPerGroupCount]) {

     }else{
         UIButton *cardButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
         cardButton.frame = CGRectMake(x, y, 140, 37);
         cardButton.tag = i;
         [cardButton setTitle:[NSString stringWithFormat:@"%@ (%i)", [group groupName],[player getCardGroupCount:group]] 
                     forState:UIControlStateNormal];
         [cardButton addTarget:self action:@selector(playerCardClicked:)    forControlEvents:UIControlEventTouchUpInside];
         [[self view] addSubview:cardButton]; 
         //NSLog(@"Card group added to view %@", [group groupName]);
         if( i == 2 || i == 5 || i == 8 || i == 11) {
              x += 157;
              y = 157;
         }else{
              y += 45;
         }
       }
    }
}

2 个答案:

答案 0 :(得分:2)

看起来groupName已经取消分配。它可能发生在两种情况下:

  • 你忘了把它留在某个地方。您确定group保留了它吗?
  • 你释放的地方不应该。

我可以为您提出两种解决问题的方法:

  • 仔细阅读您的代码,以确保您正确管理groupName生命周期。
  • 您可以创建MyString课程,从NSString继承,并将groupName声明为MyString。然后,您可以将断点放入dealloc方法并查找何时取消分配。它可以帮助您找出groupName生命周期的问题。

答案 1 :(得分:1)

首先,不要为方法get*命名。 get在Cocoa / iOS中有一个非常具体的含义,而通用的getter则不然。

接下来,您是否在代码中使用了“构建和分析”?修复它识别的所有问题。

最后,发布崩溃发生地的回溯。另外,发布与设置和管理过度释放的对象相关的所有代码。