从UITableView删除行会导致崩溃

时间:2012-10-17 16:09:57

标签: ios uitableview sdk crash

我在从表格视图中删除行时遇到问题。这是按下行上的按钮时调用的代码。我已经使用tag参数告诉我我正在处理哪一行,这就是为什么我在最后调用reloadTableView来重新应用所有标签。如果我更新可见行,我就崩溃了。所以我一定在做错了吗?

- (void) deleteLineItem:(id)sender
{
    UIButton *deleteBtn = sender; // Need to get tag (which was set to table row)
    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:(deleteBtn.tag/3) inSection:0];
    NSLog(@"Removed entry at %d, with tag %d", indexPath.row, deleteBtn.tag);
    [self.productItems removeObjectAtIndex:indexPath.row];

    [self.tableview beginUpdates];
    [self.tableview deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationRight];
    [self.tableview endUpdates];

    // Hack to keep table animation ok as we have to do it after the row delete above
    [self performSelector:@selector(reloadTableview) withObject:nil afterDelay:0.35];
}

在这种情况下,表格中有两行。 数据源如下:

Printing description of self->productItems:
(__NSArrayM *) productItems = 0x084fa3b0 @"2 objects"

indexPath如下:

Printing description of indexPath:
<NSIndexPath 0x1069bff0> 2 indexes [0, 1]

当调用endUpdates metod时,我在控制台中遇到以下崩溃

2012-10-17 17:04:33.424 myAppname[5782:15203] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 1 beyond bounds [0 .. 0]'
*** First throw call stack:
(0x1bf0022 0x1918cd6 0x1bdcd88 0xa5553 0xa576b 0x925420 0x963284 0x9633d0 0x925219 0x8fd4f2 0x8fa4c3 0x9050b7 0x9050e5 0xa6ae1 0x1bf1e99 0x87814e 0x8780e6 0x91eade 0x91efa7 0x91e266 0xb39a1a 0x1bc499e 0x1b5b640 0x1b274c6 0x1b26d84 0x1b26c9b 0x25007d8 0x250088a 0x875626 0x1f2ba 0x2ba5)
terminate called throwing an exception(lldb)

我不知道为什么会导致问题。

3 个答案:

答案 0 :(得分:1)

代码看起来不太健壮。好像你已经将deleteBtn.tag设置为一个不好的值(在3到5之间,更准确地说),你只有一个单元格。只是一个猜测。

我使用的这种任务的更强大的技术是在我的UITableViewCell子类中实现IBAction,然后通过委托和单元本身作为参数将请求传播到控制器。在控制器中,我通过

检索indexPath
[self.tableView indexPathForCell:cell];

这样我就可以避免这种黑客攻击。

答案 1 :(得分:0)

@ilimiacs是的,这是正确的,这是一个很好的方法。但是单元格很复杂,有两个按钮和两个文本字段。

标签用于通过除以3来确定我所在的单元格以获得行(每个单元使用3个标签,0,1,2)。然后标签3将是第1行,这就是我除以3的原因。

但我确实有那里的细胞类,我会看一下使用委托来实现它的可行性,按钮很容易,但文本字段不是那么容易,因为它是一个表单,我们有下一个/上一个按钮带你从一个字段到另一个字段,标签使这很容易。

无论如何,我会接受这个答案,因为它肯定有帮助,也许我可以把它变成完整的解决方案。

答案 2 :(得分:0)

@ilmiacs感谢您的建议。我按照你的说法实现了,摆脱了标签,现在一切都在表现。重新实现它有点痛苦,但它导致了更少的hacky和更易读的代码。

我能够更新第一行,而不是重新计算剩余行的所有标记值。我需要从第一行中删除删除按钮,如果它是您看到的最后一行...正如您所看到的那样,它现在更直接了。

- (void) deleteCell:(NSIndexPath *)indexPath
{
    NSIndexPath *firstRow = [NSIndexPath indexPathForRow:0 inSection:0];
    [self.productItems removeObjectAtIndex:indexPath.row];

    [self.tableview beginUpdates];
    [self.tableview deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationRight];
    [self.tableview reloadRowsAtIndexPaths:[NSArray arrayWithObject:firstRow] withRowAnimation:UITableViewRowAnimationNone];
    [self.tableview endUpdates];
}

谢谢...