简体   繁体   English

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

[英]NSInvalidArgumentException when deleting cell using a different class

Update for code: Following on Matthew's answer I tried correcting my code to be more correct. 代码更新:根据Matthew的回答,我尝试更正我的代码以使其更正确。 Now the code does delete the cell but also crashes and gives an error: 现在,代码确实删除了单元格,但也崩溃并给出了错误:

* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '* -[__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from objects[0]' *由于未捕获的异常“ NSInvalidArgumentException”而终止应用程序,原因:“ * -[__ NSPlaceholderArray initWithObjects:count:]:尝试从对象[0]中插入零对象”

The code below is from an action called checkboxTapped which is in my CustomCell code. 以下代码来自我的CustomCell代码中一个名为checkboxTapped的操作。 Once action is fired it gives the error. 一旦动作被触发,就会产生错误。 I figured out that my indexPath is equal to NULL , and thats most likely the issue. 我发现我的indexPath等于NULL ,这很可能是问题所在。 But I don't know how to fix it. 但是我不知道如何解决。

[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];

Old: I looked through my code and I printed my array I was using and it appears to be fine, yet this error still persists. 旧的:我查看了我的代码,并打印了我正在使用的数组,这看起来很好,但是此错误仍然存​​在。

* Terminating app due to uncaught exception 'NSRangeException', reason: '* -[__NSArrayM removeObjectAtIndex:]: index 1 beyond bounds [0 .. 0]' *由于未捕获的异常'NSRangeException'而终止应用程序,原因:'* -[__ NSArrayM removeObjectAtIndex:]:索引1超出范围[0 .. 0]'

My guess was that it had something to do with my indexPath but it doesn't make much different how much I change it. 我的猜测是它与indexPath但是我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];
}

In your code [indexPath row] is going to return the value of [array count]. 在您的代码中,[indexPath row]将返回[array count]的值。 That's unlikely to be what you want. 那不可能是您想要的。 If your array has zero objects in it, you are going to attempt to remove the object at index 0. But there will be no objects and you'll get an error. 如果您的数组中有零个对象,则将尝试删除索引为0的对象。但是将没有对象,并且会出现错误。 If your array has 1 object in it, you're going to attempt to remove the object at index 1. Again, that will fail, because there is no object at index 1, just one object at index 0. 如果数组中有1个对象,则将尝试删除索引1处的对象。同样,这将失败,因为索引1处没有对象,索引0处只有一个对象。

If you want to remove the last object in an array you need to use an index that is count-1. 如果要删除数组中的最后一个对象,则需要使用count-1的索引。 You may also need to check to see if the array is empty, if that case can occur. 您可能还需要检查数组是否为空,如果可能会发生这种情况。

Updated in response to follow up in comment 更新以回应评论中的跟进

You don't want to do anything indexPathWithIndex . 您不想做任何indexPathWithIndex As a first step, try modifying your code along the following lines: 作为第一步 ,尝试大意如下修改代码:

-(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
}

All this said, it looks as if there are other things going on here. 说了这么多,看来这里还有其他事情。

What's happening with array ? array发生了什么? You create this, remove an item from it and the discard the pointer to it. 您创建它,从中删除一个项目并丢弃指向它的指针。 Is that what you really want to do. 那是您真正想要做的。 A more common pattern would be to get the pointer to the array from the other object and remove the item at the end of it here. 一种更常见的模式是从另一个对象获取指向数组的指针,并在此处删除其末尾的项目。

It's not clear from your code how you are updating the table's data source. 从代码中还不清楚如何更新表的数据源。 When using deleteRowsAtIndexPaths:withRownAnimation you need to make sure the table's data source will return one row less than it did last time it was asked with tableView:numberOfRowsInSection: . 使用deleteRowsAtIndexPaths:withRownAnimation您需要确保表的数据源返回的行数比上次使用tableView:numberOfRowsInSection:询问时返回的行少。 From your code it's not clear how the tableView dataSource is going to know there's one less item, unless, perhaps, it's looking at whatever it is that db is pointing to in order to find this out. 从您的代码中,还不清楚tableView dataSource如何知道少了一个项目,除非,也许正在寻找db指向的内容以找出答案。

More fundamentally, with a typical design pattern the tableView is going to be released when you release the parent view, so whatever it points to after `[parent release]' is going to do something undefined and is likely to crash at least some of the time. 从根本上讲,使用典型的设计模式,当您释放父视图时,tableView将被释放,因此在[parentparent]之后,它指向的所有内容都将做未定义的操作,并且可能会使至少一些崩溃。时间。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM