当TableView的DataSource阵列发生变化时,应用程序崩溃

时间:2009-06-22 21:24:04

标签: objective-c cocoa

我有一个包含5个项目的数组,也用作tableview的内容。在笔尖中有一个按钮,可以将数组的内容更改为5个不同的项目。但是,当我单击该按钮时,应用程序崩溃并出现EXC_BAD_ACCESS。我在objc_exception _throw上设置了一个断点,并确认了我的怀疑。坏方法是

- (id)tableView:(NSTableView *)wordsTableView
objectValueForTableColumn:(NSTableColumn *)column
            row:(int)rowIndex
{
    return [[currentCard words] objectAtIndex:rowIndex];
}

currentCard是GameCard类的一个实例,它的数组单词是有问题的数组。在第一次启动时,它工作正常,但如果我尝试更改它,崩溃。

---------- ---------- EDIT

在AppController的awakeFromNib中:我有这个

currentCard = [[GameCard alloc] init];

在按钮的IBAction中,我有这个:

[currentCard release];
currentCard = [[GameCard alloc] init];

启用僵尸后,当我点击按钮时,我从GDB获取此信息:

2009-06-22 18:55:03.368 25WordsMax [19761:813] *** - [CFArray objectAtIndex:]:发送到解除分配的实例0x14ba00的消息

指的是数据源方法。我一直试图追踪内存错误数小时,但我错过了它。

我非常沮丧,我评论了每一个保留&在代码中发布(没有自动释放)仍然得到2009-06-22 19:41:58.564 25WordsMax [21765:813] *** - [CFArray objectAtIndex:]:当我按下按钮时发送到解除分配的实例0x14c330的消息。 / p>

什么是数据源方法?我不是在调用reloadData。如果在我的数据源方法中,我为每行返回@“A Word”,一切运行正常。在GDB中,我甚至可以看到我的NSLogs打印出新数组的内容,一切顺利。只有在调用问题中看到的数据源方法时才会发生任何问题。

4 个答案:

答案 0 :(得分:5)

  

2009-06-22 18:55:03.368 25WordsMax [19761:813] *** - [CFArray objectAtIndex:]:发送到解除分配的实例0x14ba00的消息

仔细阅读。接收者是CFArray的一个实例,消息选择器是objectAtIndex:

解除分配的实例是一个数组,而不是游戏卡。

您的游戏卡拥有阵列,因此必须以某种方式保留它。这意味着您必须:

  1. 使用alloc和init创建数组(而不是自动释放它)。
  2. 保留它。
  3. 制作自己的副本。 (如果你从另一个对象接收一个数组,就像在你的setter中一样,因为你收到的数组可能是可变的,你不希望另一个对象改变“你的”数组。)
  4. 如果您综合了访问者,请将该属性声明为@property(retain)@property(copy)。请注意,如果您想要一个可变副本,这将不起作用;在这种情况下,你必须自己实现setter。

答案 1 :(得分:1)

听起来你在某个地方有一个引用计数错误,这不能仅从那段代码中调试。尝试使用NSZombieEnabled = 1运行,然后查找保留/释放错误,您可以在其中管理任何有关僵尸警告的对象。

答案 2 :(得分:0)

NSZombie告诉你,从[currentCard words]返回的对象正在某处释放,然后你再次使用它。检查对该变量的所有分配,并确保不将其设置为自动释放的对象。然后检查发送给它的所有发布和自动发布消息。

答案 3 :(得分:0)

可能有助于查看GameCard Init和GameCard dealloc方法。

另外要验证您认为问题的方法是问题,我会检查nil

if( [currentCard words] != nil )
    return [[currentCard words] objectAtIndex:rowIndex];

else
    return @"Blah!";