您好我很难解决此错误。
由于未捕获的异常终止应用程序' NSInternalInconsistencyException',原因:'索引3处的索引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
答案 0 :(得分:37)
问题出在您的configureCell:atIndexPath
方法中。不幸的是,Core Data Xcode模板中提供的实现有一些错误。你的崩溃就是其中之一。
NSFetchedResultsController
方法objectAtIndexPath:
调用不太安全。如果你给它一个超出范围的NSIndexPath它会崩溃,你看到的异常。这在类引用中提到:
如果indexPath没有在获取结果中描述有效的索引路径,则会引发异常。
这就像访问数组一样:无论何时通过索引访问数组,都应该首先进行边界检查。 objectAtIndexPath:
的边界检查如下:
id result = nil;
if ([[self.fetchedResultsController sections] count] > [indexPath section]){
id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:[indexPath section]];
if ([sectionInfo numberOfObjects] > [indexPath row]){
result = [self.fetchedResultsController objectAtIndexPath:indexPath];
}
}
这有点复杂,但有必要。这解决了这个例外。
您获得异常的原因是NSFetchedResultsController的状态与tableview的状态不同步。当你的崩溃发生时,tableView只询问你的委托方法(numberOfSectionsInTableView
和tableView:numberOfRowsInSection:
的行和节的数量。当它询问时,NSFetchedResultsController中有数据,并给出正值(1节)但是,在发生这种情况和崩溃之间,NSFetchedResultsController表示的实体已从NSManagedObjectContext中删除。现在使用过时的cellForRowAtIndexPath:
参数调用indexPath
。
看起来egoRefreshScrollViewDataSourceDidFinishedLoading
通过调整滚动视图的内容视图来重建tableView - 并且在重新提取和重新加载之前调用cellForRowAtIndexPath:
- 你的tableView。这需要在egoRefreshScrollViewDataSourceDidFinishedLoading
正在做的事情之前发生。 egoRefreshScrollViewDataSourceDidFinishedLoading
导致使用陈旧的索引路径调用cellForRowAtIndexPath:
。
真正的问题可能在于您的NSFetchedResultsControllerDelegate
方法。当您的实体被删除时,应调用这些实体以从tableView中删除项目。这似乎没有发生在这里。
简短版本,将[self.tableView reloadData];
向上移动一行:
[self.tableView reloadData];
[_refreshHeaderView egoRefreshScrollViewDataSourceDidFinishedLoading:self.tableView];
答案 1 :(得分:1)
这是我根据接受的答案编写的辅助方法,但在 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
}