删除Tableview NSFetchedResultsController中的最后一部分行

时间:2014-12-07 18:31:14

标签: ios objective-c tableview nsfetchedresultscontroller

我正在构建一个通用的FetchedResultsController DataSource类,用于我的所有TableViewControllers,其中一些有多个部分,有些没有(像任何Project一样)。

问题是当Fetched Results Controller有多个部分( sectionNameKeyPath 不为null)时,如果TableView部分只有一行,didChangeObject上的删除逻辑必须删除整个部分,但是如果在Fetched Results Controller定义(sectionNameKeyPath = nil)上只设置了一个部分,则相同的逻辑不起作用。

任何人都知道如何在didChangeObject上实现泛型删除逻辑以防止出现这种错误?

例外:

  

从代表处获取了一个例外   NSFetchedResultsController在调用期间   -controllerDidChangeContent :.无效更新:无效的节数。表视图中包含的节数   更新(1)必须等于包含的部分数   更新前的表视图(1),加号或减号   插入或删除的部分(0插入,1删除)。用户信息   (空)

//Fetched Results Controller Definition on My Model Class
+ (NSFetchedResultsController*)fetchedResultsController
{
    NSFetchRequest* request = [NSFetchRequest fetchRequestWithEntityName:[self.class entityName]];

    //request.predicate = [NSPredicate predicateWithFormat:@"parent = %@", self];
    request.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"dueDate" ascending:NO]];

    [request setFetchLimit:50];

    //Generate an error
    return [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:Store.defaultManagedObjectContext sectionNameKeyPath:nil cacheName:nil];

    //Works Fine
    //return [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:Store.defaultManagedObjectContext sectionNameKeyPath:@"shortDueDate" cacheName:nil];
}


//Fetched Results Controller Generic Data Source Class
- (void)controller:(NSFetchedResultsController*)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath*)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath*)newIndexPath
{
    if (type == NSFetchedResultsChangeInsert) {
        [self.tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
    } else if (type == NSFetchedResultsChangeMove) {
        [self.tableView moveRowAtIndexPath:indexPath toIndexPath:newIndexPath];
    } else if (type == NSFetchedResultsChangeDelete) {

        BOOL deleteSection = FALSE;

        //If have only one section and its the last row then delete entire section
        if ((self.tableView.numberOfSections == 1) && ([self.tableView numberOfRowsInSection:[indexPath section]] == 1 )) {
            deleteSection = TRUE;
        }

        if (deleteSection) {
            [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:YES];
        } else {
            [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
        }
    } else {
        NSAssert(NO,@"");
    }
}

2 个答案:

答案 0 :(得分:1)

如果您实施:

- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
       atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type

然后FRC将为您确定是否需要插入或删除部分。

答案 1 :(得分:0)

Swift 4.2

在处理NSFEtchedResultsController和CoreData时,我遇到了类似的问题。

  1. 覆盖func tableView(_:, commit:, forRowAt:)

    override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
    if editingStyle == .delete {
        let commit = fetchedResultsController.object(at: indexPath)
    
        let sections = fetchedResultsController.sections
        let section = sections![indexPath.section]
    
        // numberOfObjectsInCurrentSection is the class' variable
        numberOfObjectsInCurrentSection = section.numberOfObjects
    
        container.viewContext.delete(commit)
        saveContext()
      }
    }
    

  1. 实施此NSFetchedResultsControllerDelegate方法。这里 您将检查以前剩余的项目数 所选表格视图的部分,然后删除一行或(如果 该部分只有一行左右)

    func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
     switch type {
     case .delete:
        tableView.beginUpdates()
    
        if numberOfObjectsInCurrentSection! > 1 {
            tableView.deleteRows(at: [indexPath!], with: .automatic)
        } else {
            let indexSet = NSMutableIndexSet()
            indexSet.add(indexPath!.section)
            tableView.deleteSections(indexSet as IndexSet, with: UITableViewRowAnimation.fade)
        }
    
        tableView.endUpdates()
    default:
        break
    }
    }