NSRangeException - 超出范围的索引 (2008) (1)
Posted
技术标签:
【中文标题】NSRangeException - 超出范围的索引 (2008) (1)【英文标题】:NSRangeException - Index (2008) beyond bounds (1) 【发布时间】:2014-01-05 16:18:44 【问题描述】:我试图在从核心数据模型中删除 UITableViewCell 之前获取它的内容,以便对其内容采取行动。如果 Core Data 模型中只有一项并且我从 UITableView 中将其删除,则应用仅有时会抛出 2014-01-05 11:10:26.189 Nibbles[43609:70b] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[_PFArray objectAtIndex:]: index (2008) beyond bounds (1)'
我最大的困惑是,这只发生在 UITableView 中的一项上,并且不会 100% 发生。如果您需要查看任何其他代码,请告诉我。
这是我正在使用的代码。粗体线是导致错误的原因,因为它永远不会通过 NSLog 到达控制台。
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
if (editingStyle == UITableViewCellEditingStyleDelete)
NSLog(@"Delete button pressed!");
FoodListCell *cell = (FoodListCell*)[tableView cellForRowAtIndexPath:indexPath];
NSLog(@"DEBUG | Selected Cell: %@", cell);
NSString *foodOrActivity = cell.foodNameLabel.text;
NSString *points = cell.foodPointsLabel.text;
NSManagedObjectContext *localContext = [NSManagedObjectContext MR_contextForCurrentThread];
[[self.fetchedResultsController objectAtIndexPath:indexPath] MR_deleteInContext:localContext];
[localContext MR_saveOnlySelfAndWait];
NSIndexPath *path = [NSIndexPath indexPathForRow:indexPath.row inSection:0];
NSManagedObject *deleteObject = [_fetchedResultsController objectAtIndexPath:path];
[managedObjectContext deleteObject:deleteObject];
这是完整的堆栈跟踪:
2014-01-05 11:10:26.189 Nibbles[43609:70b] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[_PFArray objectAtIndex:]: index (2008) beyond bounds (1)'
*** First throw call stack:
(
0 CoreFoundation 0x01cd45e4 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x01a578b6 objc_exception_throw + 44
2 CoreFoundation 0x01cd43bb +[NSException raise:format:] + 139
3 CoreData 0x00280755 -[_PFArray objectAtIndex:] + 133
4 CoreData 0x002f9778 -[_PFMutableProxyArray objectAtIndex:] + 120
5 CoreData 0x00382c1f -[NSFetchedResultsController objectAtIndexPath:] + 255
6 Nibbles 0x0000660d -[FoodListViewController tableView:commitEditingStyle:forRowAtIndexPath:] + 685
7 UIKit 0x008b5ba3 -[UITableView animateDeletionOfRowWithCell:] + 107
8 UIKit 0x00a35695 -[UITableViewCell _swipeDeleteButtonPushed] + 70
9 libobjc.A.dylib 0x01a69874 -[NSObject performSelector:withObject:withObject:] + 77
10 UIKit 0x007c70c2 -[UIApplication sendAction:to:from:forEvent:] + 108
11 UIKit 0x007c704e -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 61
12 UIKit 0x008bf0c1 -[UIControl sendAction:to:forEvent:] + 66
13 UIKit 0x008bf484 -[UIControl _sendActionsForEvents:withEvent:] + 577
14 UIKit 0x008be733 -[UIControl touchesEnded:withEvent:] + 641
15 UIKit 0x00b39c7f _UIGestureRecognizerUpdate + 7166
16 UIKit 0x0080419a -[UIWindow _sendGesturesForEvent:] + 1291
17 UIKit 0x008050ba -[UIWindow sendEvent:] + 1030
18 UIKit 0x007d8e86 -[UIApplication sendEvent:] + 242
19 UIKit 0x007c318f _UIApplicationHandleEventQueue + 11421
20 CoreFoundation 0x01c5d83f __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15
21 CoreFoundation 0x01c5d1cb __CFRunLoopDoSources0 + 235
22 CoreFoundation 0x01c7a29e __CFRunLoopRun + 910
23 CoreFoundation 0x01c79ac3 CFRunLoopRunSpecific + 467
24 CoreFoundation 0x01c798db CFRunLoopRunInMode + 123
25 GraphicsServices 0x0285e9e2 GSEventRunModal + 192
26 GraphicsServices 0x0285e809 GSEventRun + 104
27 UIKit 0x007c5d3b UIApplicationMain + 1225
28 Nibbles 0x000236ad main + 141
29 libdyld.dylib 0x031b470d start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
【问题讨论】:
方法的其余部分IS很重要,因为错误来自objectAtIndexPath
调用,未包含在您发布的代码中。
@coneybeare 呃不知道我是怎么错过的 - 将其余代码添加到函数中。
正如@coneybeare 所说,您缺少该方法的代码,因为它抱怨您的 NSFetchedResultsController 对 objectAtIndexPath 的调用
@valheru 将 NSFetchedResultsController 代码的其余部分添加到原始帖子中。我很抱歉跳过它。
【参考方案1】:
常规模式是访问模型(不是通过表格单元格,而是直接从模型中)。做任何你需要做的事情,然后从你的模型中删除它,然后从你的表中删除它......
该错误意味着该方法正在访问的 localContext 与报告模型中项目数的 MOC 不同(或处于不同状态)(用于 numberOfRowsInSection
:)
在继续记录已删除对象的状态或将其删除之前。修复获取该对象的代码并仅对其进行 NSLog 处理。获取该对象的代码应该完全匹配在您的cellForRowAtIndexPath
: 中获取它的代码,并且那里使用的 MOC 应该完全匹配 numberOfRowsInSection
: MOC。
【讨论】:
这是我的numberOfRowsInSection
代码:id sectionInfo = [[_fetchedResultsController sections] objectAtIndex:section]; return [sectionInfo numberOfObjects];
是的,所以 _fetchedResultsController 是您应该在所有委托和数据源方法中使用的,以获取您的模型。
我想我的另一个问题是是否需要带有[managedObjectContext deleteObject:deleteObject];
的第二组代码?我刚刚注释掉了@valheru 在下面发布的三行代码,现在我的对象从模型和 UITableView 中删除了。
@valhero 是正确的,不需要构造 indexPath。代码需要的那个被传递给委托。【参考方案2】:
NSIndexPath *path = [NSIndexPath indexPathForRow:indexPath.row inSection:0];
NSManagedObject *deleteObject = [_fetchedResultsController objectAtIndexPath:path];
[managedObjectContext deleteObject:deleteObject];
在这里,您将获取第 0 节中行的索引路径并将其删除。
您已经有了要删除的行/单元格/部分的索引路径,那么为什么要尝试仅在第 0 部分中删除该行?
在这一行尝试一个断点并添加一些日志记录以显示第 0 节中的哪一行试图被删除。
【讨论】:
所以我尝试将其更改为这个,但它仍然抱怨 - 看起来代码来自上面的部分。NSManagedObject *deleteObject = [_fetchedResultsController objectAtIndexPath:indexPath]; [managedObjectContext deleteObject:deleteObject];
啊,但仔细看看。 deleteObject 实际上是从第 0 节的怪异 indexPath 分配的。不是原始 indexPath: NSIndexPath *path = [NSIndexPath indexPathForRow:indexPath.row inSection:0]; NSManagedObject *deleteObject = [_fetchedResultsController objectAtIndexPath:path];
在您看来,我需要这两种方法吗?我注释掉了您发布的那段代码,现在发生了删除,并且该对象已从 MOC 中删除。也许第二组代码超出了范围,因为该对象已被删除。以上是关于NSRangeException - 超出范围的索引 (2008) (1)的主要内容,如果未能解决你的问题,请参考以下文章
异常'NSRangeException',原因:'*** -[__NSArrayM objectAtIndex:]:索引 19 超出范围 [0 .. 18]'
带有 Sections [indexPath Row] 的 TableView 中的 NSRangeException 超出范围
修改 NSFetchRequest 为空数组生成 NSRangeException 索引 0 超出范围
由于未捕获的异常“NSRangeException”而终止应用程序。 [__NSArrayM objectAtIndex:]:索引 33 超出范围 [0 .. 32]'
异常“NSRangeException”,原因:“*** -[__NSArray0 objectAtIndex:]:索引 0 超出了空 NSArray 的范围”
由于未捕获的异常“NSRangeException”而终止应用程序,原因:“*** -[__NSArrayM objectAtIndex:]:索引 0 超出空数组的范围”