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

时间:2014-07-31 02:29:41

标签: ios core-data nsfetchedresultscontroller

您好我很难解决此错误。

  

由于未捕获的异常终止应用程序' 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

2 个答案:

答案 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只询问你的委托方法(numberOfSectionsInTableViewtableView: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
}