使用其他类删除单元格时,NSInvalidArgumentException [英] NSInvalidArgumentException when deleting cell using a different class

查看:57
本文介绍了使用其他类删除单元格时,NSInvalidArgumentException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

更新代码:在Matthew回答之后,我尝试更正我的代码以使其更正确.现在,代码确实删除了单元格,但同时崩溃并给出了错误:

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

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

  [self.textLabel setTextColor:[UIColor grayColor]];[self.detailTextLabel setTextColor:[UIColor grayColor]];parent = [[ViewController alloc] init];db = [[DataObject alloc] init];NSIndexPath * indexPath = [[父tableView] indexPathForSelectedRow];[[父数组] removeObjectAtIndex:[indexPath行]];[db deleteTaskAtIndex:[indexPath row]];[[parent tableView] deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];[db版本];[上级发布]; 

旧的:我浏览了我的代码,并打印了我正在使用的数组,看起来不错,但此错误仍然存​​在.

*由于未捕获的异常'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];[上级发布];NSIndexPath * indexPath = [NSIndexPath indexPathForRow:[array count] inSection:1];[array removeObjectAtIndex:[indexPath row]];[db deleteTaskAtIndex:[indexPath row]];[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationTop];[数组发布];[tableView endUpdates];[tableView reloadData];} 

解决方案

在您的代码中,[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];//看起来很奇怪-轻按CheckBox时,此viewController的实例是否处于活动状态?如果是这样,您不想创建一个新的,您想访问现有的一个UITableView * tableView = parent.tableView;[上级发布];//这看起来很简单-当您释放父对象时,它也不会释放tableView吗?int lastRow = [数组数]-1;如果(lastRow == 0){返回;//如果表中没有行则保释}NSMutableArray * array = [[NSMutableArray alloc] initWithArray:parent.array];[array removeObjectAtIndex:lastRow];//不清楚这会做什么,因为稍后会舍弃对数组的引用[db deleteTaskAtIndex:lastRow];NSIndexPath * indexPath = [NSIndexPath indexPathForRow:lastRow inSection:1];[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationTop];[数组发布];//[tableView endUpdates];//没有匹配的beginUpdates,无论如何您都只能进行一次更改操作-省略此操作//[tableView reloadData];//如果您保留这一行,则不会看到删除动画-如果您只想删除一行,通常不会使用reloadData,至少不要使用动画} 

所有这些,看起来好像还有其他事情在发生.

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

从代码中尚不清楚如何更新表的数据源.使用 deleteRowsAtIndexPaths:withRownAnimation 时,您需要确保表的数据源返回的行数比上次使用 tableView:numberOfRowsInSection:询问时返回的行少.从您的代码中,还不清楚tableView dataSource如何知道少一个项目,除非,也许为了找到答案,它正在查看 db 指向的内容.

从根本上讲,使用典型的设计模式,当您释放父视图时,tableView将被释放,因此,在"[parent release]"之后指向的内容将执行未定义的操作,并且至少会崩溃有时候.

Update for code: Following on Matthew's answer I tried correcting my code to be more correct. 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]'

The code below is from an action called checkboxTapped which is in my CustomCell code. Once action is fired it gives the error. I figured out that my indexPath is equal to NULL, and thats most likely the issue. 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]'

My guess was that it had something to do with my indexPath but it doesn't make much different how much I change it.

-(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]. 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. 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.

If you want to remove the last object in an array you need to use an index that is 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. 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? 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:. 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.

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.

这篇关于使用其他类删除单元格时,NSInvalidArgumentException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆