由于未捕获的exception’NSInternalInconsistencyException’而终止应用程序,原因:’索引0处的索引3处没有对象’

嗨,我很难解决这个错误。

由于未捕获的exception’NSInternalInconsistencyException’而终止应用程序,原因:’索引0处的索引3处没有对象’

当我删除coredata中的所有实体并重新获取它时,存在该错误。

CALL API

self.fetchedResultsController = nil; [NSFetchedResultsController deleteCacheWithName:nil]; [api requestForMenuCategory:@"details" managedObjectContext:self.managedObjectContext delegate:self]; 

当API无法获取数据时执行

  if (![self.fetchedResultsController performFetch:&error]) { NSLog(@"%@",[error description]); } else{ NSLog(@"NUMBER OF FETCH %d",[[_fetchedResultsController fetchedObjects] count]); [_refreshHeaderView egoRefreshScrollViewDataSourceDidFinishedLoading:self.tableView]; [self.tableView reloadData]; } 

获取的数量说它是0,但我不知道为什么我的tableview中仍然有数据,过了一段时间它崩溃了

编辑

这是我的部分行数,我没有部分的数量,因为默认值是1未实现时

 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [[_fetchedResultsController fetchedObjects] count]; 

}

编辑2

 *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'no object at index 3 in section at index 0' *** First throw call stack: ( 0 CoreFoundation 0x00df65e4 __exceptionPreprocess + 180 1 libobjc.A.dylib 0x042a08b6 objc_exception_throw + 44 2 CoreData 0x03310cae -[NSFetchedResultsController objectAtIndexPath:] + 398 3 DogDuck 0x0014c692 -[TestMenuViewController configureCell:atIndexPath:] + 146 4 DogDuck 0x0014c583 -[TestMenuViewController tableView:cellForRowAtIndexPath:] + 227 5 UIKit 0x01e2361f -[UITableView _createPreparedCellForGlobalRow:withIndexPath:] + 412 6 UIKit 0x01e236f3 -[UITableView _createPreparedCellForGlobalRow:] + 69 7 UIKit 0x01e07774 -[UITableView _updateVisibleCellsNow:] + 2378 8 UIKit 0x01e05b1f -[UITableView _setNeedsVisibleCellsUpdate:withFrames:] + 171 9 UIKit 0x01e1b111 -[UITableView _rectChangedWithNewSize:oldSize:] + 490 10 UIKit 0x01e1b6dd -[UITableView setBounds:] + 279 11 UIKit 0x01daac17 -[UIScrollView setContentOffset:] + 690 12 UIKit 0x01e1c1d1 -[UITableView setContentOffset:] + 314 13 UIKit 0x01dc7cae -[UIScrollView(UIScrollViewInternal) _adjustContentOffsetIfNecessary] + 2622 14 UIKit 0x01daad82 -[UIScrollView setContentInset:] + 143 15 UIKit 0x01e1c302 -[UITableView setContentInset:] + 280 16 DogDuck 0x00133be6 -[EGORefreshTableHeaderView egoRefreshScrollViewDataSourceDidFinishedLoading:] + 310 17 DogDuck 0x0014c2a8 -[TestMenuViewController doneLoading] + 440 18 DogDuck 0x00006192 __66-[BoogieAPI requestForMenuCategory:managedObjectContext:delegate:]_block_invoke + 1266 19 Foundation 0x02ce2695 __67+[NSURLConnection sendAsynchronousRequest:queue:completionHandler:]_block_invoke_2 + 151 20 Foundation 0x02c42945 -[NSBlockOperation main] + 88 21 Foundation 0x02c9b829 -[__NSOperationInternal _start:] + 671 22 Foundation 0x02c18558 -[NSOperation start] + 83 23 Foundation 0x02c9daf4 __NSOQSchedule_f + 62 24 libdispatch.dylib 0x048ac4b0 _dispatch_client_callout + 14 25 libdispatch.dylib 0x0489a75e _dispatch_main_queue_callback_4CF + 340 26 CoreFoundation 0x00e5ba5e __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 14 27 CoreFoundation 0x00d9c6bb __CFRunLoopRun + 1963 28 CoreFoundation 0x00d9bac3 CFRunLoopRunSpecific + 467 29 CoreFoundation 0x00d9b8db CFRunLoopRunInMode + 123 30 GraphicsServices 0x0524c9e2 GSEventRunModal + 192 31 GraphicsServices 0x0524c809 GSEventRun + 104 32 UIKit 0x01d34d3b UIApplicationMain + 1225 33 DogDuck 0x000027cd main + 125 34 DogDuck 0x00002745 start + 53 ) libc++abi.dylib: terminating with uncaught exception of type NSException (lldb) 

附加注意正在调用行的单元格,但fetchedobject为0

问题出在configureCell:atIndexPath方法中。 不幸的是,Core Data Xcode模板中提供的实现有一些错误。 你的崩溃就是其中之一。

NSFetchedResultsController方法objectAtIndexPath:调用不是很安全。 如果你给它一个超出范围的NSIndexPath它会崩溃,你看到的exception。 这在类引用中提到:

如果indexPath未在获取结果中描述有效的索引路径,则会引发exception。

这就像访问数组一样:无论何时通过索引访问数组,都应该首先进行边界检查。 objectAtIndexPath:的边界检查objectAtIndexPath:如下所示:

 id result = nil; if ([[self.fetchedResultsController sections] count] > [indexPath section]){ id  sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:[indexPath section]]; if ([sectionInfo numberOfObjects] > [indexPath row]){ result = [self.fetchedResultsController objectAtIndexPath:indexPath]; } } 

这有点复杂,但有必要。 这解决了这个例外。

您获得exception的原因是NSFetchedResultsController的状态与tableview的状态不同步。 当您的崩溃发生时,tableView只询问您的委托方法( numberOfSectionsInTableViewtableView:numberOfRowsInSection:表示行和节的数量。当它询问时,NSFetchedResultsController中有数据,并给出正值(1节,3行)。但是在发生这种情况和崩溃之间, indexPath表示的实体已从NSManagedObjectContext中删除。现在使用过时的indexPath参数调用cellForRowAtIndexPath: indexPath

看起来egoRefreshScrollViewDataSourceDidFinishedLoading 重新获取和重新加载tableView 之前,通过调整滚动视图的内容视图和要调用的cellForRowAtIndexPath:来导致重建tableView。 这需要在egoRefreshScrollViewDataSourceDidFinishedLoading执行之前发生。 egoRefreshScrollViewDataSourceDidFinishedLoading导致使用陈旧的索引路径调用cellForRowAtIndexPath: egoRefreshScrollViewDataSourceDidFinishedLoading

真正的问题可能在于您的NSFetchedResultsControllerDelegate方法。 当您的实体被删除时,应该调用这些实体以从tableView中删除项目。 这似乎没有发生在这里。

简短的版本,移动你的[self.tableView reloadData]; 一行:

 [self.tableView reloadData]; [_refreshHeaderView egoRefreshScrollViewDataSourceDidFinishedLoading:self.tableView]; 

这是我根据接受的答案编写的辅助方法,但在Swift 3中

 func validateIndexPath(_ indexPath: IndexPath) -> Bool { if let sections = self.fetchedResultsController?.sections, indexPath.section < sections.count { if indexPath.row < sections[indexPath.section].numberOfObjects { return true } } return false } 

编辑(使用)

 override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier(), for: indexPath) if self.validateIndexPath(indexPath) { configureCell(cell: cell, indexPath: indexPath) } else { print("Attempting to configure a cell for an indexPath that is out of bounds: \(indexPath)") } return cell }