使用其他类删除单元格时出现NSInvalidArgumentException

时间:2012-02-26 12:13:16

标签: iphone sigabrt nsindexpath

代码更新:关于Matthew的回答我尝试更正我的代码更正确。现在代码确实删除了单元格,但也崩溃了,并给出了一个错误:

  

*由于未捕获的异常'NSInvalidArgumentException'而终止应用程序,原因:'* - [__ NSPlaceholderArray initWithObjects:count:]:尝试从对象[0]中插入nil对象

以下代码来自名为checkboxTapped的操作,该操作位于我的CustomCell代码中。一旦触发动作,它就会出错。我发现我的indexPath等于NULL,这很可能就是问题所在。但我不知道如何解决它。

[self.textLabel setTextColor:[UIColor grayColor]];
[self.detailTextLabel setTextColor:[UIColor grayColor]];

parent = [[ViewController alloc] init];

db = [[DataObject alloc] init];
NSIndexPath *indexPath = [[parent tableView] indexPathForSelectedRow];

[[parent array] removeObjectAtIndex:[indexPath row]];
[db deleteTaskAtIndex:[indexPath row]];

[[parent tableView] deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];

[db release];
[parent release];

旧:我查看了我的代码并打印了我正在使用的数组,看起来很好,但这个错误仍然存​​在。

  

*由于未捕获的异常'NSRangeException'而终止应用程序,原因:'* - [__ NSArrayM removeObjectAtIndex:]:索引1超出边界[0 .. 0]'

我的猜测是它与我的indexPath有关,但是我改变它的程度并没有多大差异。

-(void)checkboxTapped:(id)sender
{
    [sender setSelected:YES];

    [self.textLabel setTextColor:[UIColor grayColor]];
    [self.detailTextLabel setTextColor:[UIColor grayColor]];

    parent = [[ViewController alloc] init];
    UITableView *tableView = parent.tableView;
    NSMutableArray *array = [[NSMutableArray alloc] initWithArray:parent.array];
    [parent release];

    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[array count] inSection:1];

    [array removeObjectAtIndex:[indexPath row]];
    [db deleteTaskAtIndex:[indexPath row]];    
    [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationTop];

    [array release];

    [tableView endUpdates];
    [tableView reloadData];
}

1 个答案:

答案 0 :(得分:1)

在你的代码中[indexPath row]将返回[array count]的值。这不太可能是你想要的。如果你的数组中有零个对象,你将尝试删除索引0处的对象。但是没有对象,你会收到错误。如果你的数组中有1个对象,你将尝试删除索引1处的对象。再次,这将失败,因为索引1处没有对象,只有索引0处的一个对象。

如果要删除数组中的最后一个对象,则需要使用count-1的索引。如果可能发生这种情况,您可能还需要检查数组是否为空。

更新了以回复评论中的后续行动

您不想做任何事情indexPathWithIndex。作为第一个步骤,请尝试按以下行修改代码:

-(void)checkboxTapped:(id)sender
{
    [sender setSelected:YES];

    [self.textLabel setTextColor:[UIColor grayColor]];
    [self.detailTextLabel setTextColor:[UIColor grayColor]];

    parent = [[ViewController alloc] init];  // looks very odd - is an instance of this viewController active when the checkBox is tapped? If so, you don't want to create a new one, you want to access the existing one
    UITableView *tableView = parent.tableView;
    [parent release];  // this looks very dicey - when you release the parent, won't it release the tableView too?!

    int lastRow = [array count] - 1;
    if (lastRow == 0)
    {
         return; // bail if there are no rows in the table
    }

    NSMutableArray *array = [[NSMutableArray alloc] initWithArray:parent.array];
    [array removeObjectAtIndex: lastRow];  // not clear this will do anything as the reference to array is discarded later

    [db deleteTaskAtIndex: lastRow];   

    NSIndexPath *indexPath = [NSIndexPath indexPathForRow: lastRow inSection:1]; 
    [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationTop];

    [array release];

// [tableView endUpdates];  // there's no matching beginUpdates and you're only do one change operation anyway - leave this out

// [tableView reloadData]; // if you leave this line in, you won't see the delete animation - if you just want to delete one row, you wouldn't normally use reloadData, at least not if you want the animation
}

所有这些都说,看起来好像还有其他事情发生了。

array发生了什么?你创建它,从中删除一个项目,并丢弃指向它的指针。这是你真正想要做的。一个更常见的模式是从另一个对象获取指向数组的指针,并在此处删除它的末尾。

从代码中不清楚如何更新表的数据源。使用deleteRowsAtIndexPaths:withRownAnimation时,您需要确保表格的数据源返回的行数少于上次向tableView:numberOfRowsInSection:询问的行数。从你的代码中不清楚tableView dataSource将如何知道只有少一个项目,除非它正在查看db指向的任何内容以便找到它。

更基本的是,对于典型的设计模式,当您释放父视图时,tableView将被释放,所以无论它在“父发布”之后指向什么,都会做一些未定义的事情并且可能至少崩溃有时候。