ios - 带有 NSFetchedResultsController 的表通过添加部分移动行

标签 ios uitableview ios7 nsfetchedresultscontroller

我有带 NSFetchedResultsController 的 UITableView

NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc]
                                                             initWithFetchRequest:[self dataFetchRequest]
                                                             managedObjectContext:[MLCoreDataService sharedInstance].managedObjectContext
                                                             sectionNameKeyPath:@"checked"
                                                             cacheName:nil];
aFetchedResultsController.delegate = self;

我已经实现了

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
       atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
      newIndexPath:(NSIndexPath *)newIndexPath
{
    UITableView *tableView = self.tableView;

    switch(type) {
        case NSFetchedResultsChangeInsert:
            [tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeUpdate:
            [(MLItemTableViewCell*)[tableView cellForRowAtIndexPath:indexPath] setItem:anObject];
            break;

        case NSFetchedResultsChangeMove:

            [tableView moveRowAtIndexPath:indexPath toIndexPath:newIndexPath];
            break;
    }

    [self.tableView reloadData];
}

当我在我的行中更改实体的“选中”属性时,我接到了一个电话

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
       atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
      newIndexPath:(NSIndexPath *)newIndexPath

类型为 NSFetchedResultsChangeMove

当编辑前后的部分数量相同时,一切正常。 但是当我只有一个部分并且在编辑行应该转到下一部分时我得到以下错误

2014-07-27 17:37:43.384 mlist[34340:60b] CoreData: error: Serious application error.  Exception was caught during Core Data change processing.  This is usually a bug within an observer of NSManagedObjectContextObjectsDidChangeNotification.  Invalid update: invalid number of sections.  The number of sections contained in the table view after the update (2) must be equal to the number of sections contained in the table view before the update (1), plus or minus the number of sections inserted or deleted (0 inserted, 0 deleted). with userInfo (null)
2014-07-27 17:37:43.420 mlist[34340:60b] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of sections.  The number of sections contained in the table view after the update (2) must be equal to the number of sections contained in the table view before the update (1), plus or minus the number of sections inserted or deleted (0 inserted, 0 deleted).'

当我尝试在类型为 NSFetchedResultsChangeMove 的 didChangeObject... 方法上插入或删除时,我在部分行数方面遇到了相同的错误。

有通用的解决方法吗?正确的做法是什么?

最佳答案

问题通过自定义调用解决

[self.tableView beginUpdates];
[self.tableView endUpdates];

NSFetchedResultsControllerDelegate 完整代码

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
       atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
      newIndexPath:(NSIndexPath *)newIndexPath
{
    UITableView *tableView = self.tableView;

    switch(type) {
        case NSFetchedResultsChangeInsert:{
            [tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
        }
        break;

        case NSFetchedResultsChangeDelete:{
            [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
        }
        break;

        case NSFetchedResultsChangeUpdate:{
            [(MLItemTableViewCell*)[tableView cellForRowAtIndexPath:indexPath] setItem:anObject];
        }
        break;

        case NSFetchedResultsChangeMove:{
            if (_sectionsChanged) {
                [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
                [tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationFade];

                _sectionsChanged = NO;
            } else {
                [tableView moveRowAtIndexPath:indexPath toIndexPath:newIndexPath];
            }
        }
        break;
    }

}

- (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;
    }

    _sectionsChanged = YES;
}

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

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

关于ios - 带有 NSFetchedResultsController 的表通过添加部分移动行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24981569/

相关文章:

javascript - 有没有办法在 ios 和 android 应用程序中使用公共(public)文件夹?

ios - NSUserDefaults 返回(空)

iphone - 如何在iPhone中使用TableView时隐藏键盘?

ios - 不向当前 iOS App 用户提供更新

ios - Xcode5 : The app references non-public selectors in Payload/<AppName>. 应用/<AppName>: setAttribution:

ios - 在 iOS 7 WebView 中嵌入 YouTube 时出现白屏

ios - 为什么我的变量的值在Swift中恢复?

ios - 如何在 iOS Swift 中处理多个 UISlider 值?

ios - UITableViewController 中的键盘重叠文本字段

ios - UISearchController 结果 TableViewController 在 UISearchBar 为空时不清除结果