删除 Tableview NSFetchedResultsController 中的最后一节行

Posted

技术标签:

【中文标题】删除 Tableview NSFetchedResultsController 中的最后一节行【英文标题】:Deleting last section row in a Tableview NSFetchedResultsController 【发布时间】:2014-12-07 18:31:13 【问题描述】:

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

问题是当 Fetched Results Controller 有多个部分时(sectionNameKeyPath 不为空),如果 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,@"");
    

【问题讨论】:

你的问题到底是什么? 抱歉,Milz,无意发布!现在是正确的。 【参考方案1】:

如果你实施:

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

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

【讨论】:

【参考方案2】:

斯威夫特 5.1

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

    覆盖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()
      
    
    

    实现这个NSFetchedResultsControllerDelegate 方法。这里 你要检查之前有多少项目 选定表视图的部分,然后删除单行或(如果 该部分只有一行 lew) 整个部分

    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
    
    
    

【讨论】:

这是我现在正在遵循的解决方案.. 如果您已将实体分组并允许使用删除动画进行删除.. 正在寻找不使用全局变量的解决方案,遗憾的是这是唯一的方法似乎工作

以上是关于删除 Tableview NSFetchedResultsController 中的最后一节行的主要内容,如果未能解决你的问题,请参考以下文章

tableview 删除row ,删除组

删除 tableview 单元格并刷新视图控制器后刷新 tableview

单击按钮删除后TableView删除

删除单元格后刷新tableView

TableView 滑动删除不起作用

如何在 Firebase 中删除 tableview 项目后删除它们