2013-09-30 41 views
3

例外我有一个使用核心数据来驱动与一区段的UITableView应用。它使用所有示例项目使用的标准NSFetchedResultsControllerDelegate实现。但是,有时,但并不可靠,调用[self.tableView endUpdates]抛出以下异常:核心数据引起endUpdates

CoreData: error: Serious application error. An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:. attempt to insert row 3 into section 1, but there are only 3 rows in section 1 after the update with userInfo (null) 

,该表视图只具有在当时和空的空间(但仍滚动)可见细胞后在其他地方。没有任何修复它,但重新启动应用程序。我敢肯定,应用程序会崩溃,除了NSFetchedResultsController被捕捉异常。

应用程序重新启动后,导致该回调的数据来自正确的。果然,第1部分只有3行(或任何异常情况)。 那么,为什么地狱将核心数据可以告诉我插入不存在的行?

- (void)reloadFetch 
{ 
    NSError *error = nil; 
    if (![self.fetchedResultsController performFetch:&error]) { 
     TULogError(@"Unresolved error %@, %@", error, [error userInfo]); 
     [[TCCacheController sharedController] clearData]; 
    } 

    [self.tableView reloadData]; 
} 

- (NSFetchedResultsController *)fetchedResultsController 
{ 
    if (_fetchedResultsController == nil) { 
     NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"FeedItem"]; 
     fetchRequest.fetchBatchSize = 20; 
     fetchRequest.predicate = [NSPredicate predicateWithFormat:@"city = %@", [TCCity currentCity]]; 
     fetchRequest.sortDescriptors = @[ [NSSortDescriptor sortDescriptorWithKey:@"updatedAt" ascending:NO] ]; 
     fetchRequest.relationshipKeyPathsForPrefetching = @[ 
                  @"user", 
                  @"responses", 
                  ]; 

     _fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest 
                     managedObjectContext:[TCCacheController sharedController].mainContext 
                      sectionNameKeyPath:@"day" 
                        cacheName:nil]; 
     _fetchedResultsController.delegate = self; 

     [self reloadFetch]; 
    } 

    return _fetchedResultsController; 
} 

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller 
{ 
    [self.tableView beginUpdates]; 
} 

- (void)controller:(NSFetchedResultsController *)controller 
    didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo 
      atIndex:(NSUInteger)sectionIndex 
    forChangeType:(NSFetchedResultsChangeType)type 
{ 
    switch(type) { 
     case NSFetchedResultsChangeInsert: 
      [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; 
      break; 

     case NSFetchedResultsChangeDelete: 
      [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; 
      break; 
    } 
} 

- (void)controller:(NSFetchedResultsController *)controller 
    didChangeObject:(id)anObject 
     atIndexPath:(NSIndexPath *)indexPath 
    forChangeType:(NSFetchedResultsChangeType)type 
     newIndexPath:(NSIndexPath *)newIndexPath 
{ 
    switch(type) { 
     case NSFetchedResultsChangeInsert: { 
      [self.tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; 
      break; 
     } case NSFetchedResultsChangeDelete: { 
      [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
      break; 
     } case NSFetchedResultsChangeUpdate: { 
      [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
      break; 
     } case NSFetchedResultsChangeMove: { 
      [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
      [self.tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; 
      break; 
     } 
    } 
} 

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller 
{ 
    [self.tableView endUpdates]; 
} 
+0

你找到了一个解决方案?我遇到类似的问题。 – alivingston

回答

1

我也有类似的问题,但我将自己的自定义节从NSFetchedResultsController返回的结果。这样做时,我必须确保在管理返回的结果时调整索引路径。我错过了处理didChangeObject方法中的索引路径。

我实现了以非常蛮力的方式改变索引路径,但是在寻找这个问题时,我在这篇SO文章中发现了一个非常有用和更优雅的解决方案:NSFetchedResultsController prepend a row or section(参见JosehpH的回答)。

+0

我犯了那个错误之前一样好,但我不这样做,在这里。节和行直接从CD映射。 –

1

尝试设置tableViewSection硬编码是这样的:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 
{ 
return 1; 
//return [[self.fetchedResultsController sections] count]; 
} 

问题解决了我。