Table with NSFetchedResultsController move row with adding section

隐身守侯 提交于 2019-12-06 10:49:04

问题


I have UITableView with NSFetchedResultsController

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

I've implemented

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

When I change "checked" property of entity in my row I got a call to

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

with type NSFetchedResultsChangeMove

All is right when I have the same sections amount before editing and after. But when I have only one section and after editing row should go to the next section I got the following error

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).'

When I try to insert of delete on didChangeObject... method with type NSFetchedResultsChangeMove I have the same error with numbers of rows in sections.

Is there common way to resolve it? And what the right way to do it?


回答1:


Problem resolved by custom call of

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

Whole code of 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];    
}


来源:https://stackoverflow.com/questions/24981569/table-with-nsfetchedresultscontroller-move-row-with-adding-section

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!