滚动TableView时EXC_BAD_ACCESS

时间:2010-09-08 16:21:06

标签: iphone cocoa-touch uitableview

在我的程序中,我正在创建一个从nib文件加载的自定义UIViewCell:

[[NSBundle mainBundle] loadNibNamed:@"CustomCells" owner:self options:nil];

一旦它们被加载,我将它们设置起来并从函数返回:

if (indexpath.row == 1) {
    [nibTextInputer setupWithName:@"notes" ...];
    return nibTextInputer;
} else {
    [nibSelectInputer setupWithName:@"your_choice" ...];
    return nibSelectInputer;
};

其中nibTextInputer属于我的类(AFTextInputer),而nibSelectInputer属于我的另一个类(AFTextInputer)。这两个类都是UITableViewCell的子类。

一切正常,但是当我添加缓存时会中断:

Boolean inCache = false;
if (indexPath.row == 1) {
   UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"nibTextInputer"];
   if (cell != nil) {
      NSLog(@"%@", [cell description]); // prints out ok, correct type.
      nibTextInputer = (AFTextInputer*) cell;
      inCache = true;
   };
};

if (!inCache) {
    [[NSBundle mainBundle] loadNibNamed:@"CustomCells" owner:self options:nil];
}

一旦我添加上面的EXC_BAD_ACCESS开始出现在随机位置,通常没有其他信息,有时会出现此错误:

-[CALayer prepareForReuse]: unrecognized selector sent to instance

甚至

-[UIImage prepareForReuse]: unrecognized selector sent to instance

EXC_BAD_ACCESS的位置似乎是随机的。有时它在“出队”之后,有时在功能之外......

我想问题在于我的自定义UIViewCells的实现,但我不知道从哪里开始寻找......

想法?

2 个答案:

答案 0 :(得分:2)

您的UITableViewCell上发布了过度发布。在-[UITableViewCell prepareForReuse]返回之前调用-[UITableView dequeueReusableCellWithIdentifier:],但是当它被调用时,单元格不再存在,而是CALayer,UIImage或您无权访问的内容。

问题可能在于加载自定义单元格的方式。对于它的价值,我通常会这样做:

static NSString *CellIdentifier = @"CustomCell"; // This string should also be set in IB

CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
    [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil];
    cell = nibCell; // nibCell is a retained IBOutlet which is wired to the cell in IB
}

// Set up the cell...

答案 1 :(得分:0)

这可能是你遇到问题的地方:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"nibTextInputer"];

UITableView类将所有单元格集中到同一个池中以供重用;它不知道某些单元格是一种子类(即AFTextInputer),而某些单元格是另一种子类(即AFTextInputer)。因此,当您将if (indexPath.row == 1)块中的单元格出列时,您可能会得到错误的子类单元格。 “标识符”只是一个字符串,它向内置缓存指示您正在引用哪个表的单元格;它实际上并没有使用该字符串来挖掘缓存以找到具有匹配的子类名称的对象。

P.S。为什么使用名为Boolean的类型而不是“内置”BOOL