首页 文章

删除tableview中的行而不删除Core Data Entity

提问于
浏览
1

我有一个由NSFetchedResultsController支持的表视图 . 情况如下 . 我已经实现了"swipe to delete"一行 . 委托NSFetchedResultsController的方法和表视图的方法's are called. But the thing is, I don' t想要删除一个核心数据实体,我只想标记它的布尔标志,因为我在应用程序的其他部分需要这个实体,并希望表视图删除带动画的行 . 但是,根据错误消息,它与逻辑相反,如果您要更新实体,更新行,而不是删除它 . 有没有优雅的方法来实现它?或者唯一的选择是重新加载表?
Implementation of swipe to delete

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {

   if (editingStyle == UITableViewCellEditingStyleDelete) {
      Issue *issue = [self.fetchedResultsController objectAtIndexPath:indexPath];
      [issue setHasBeenDeleted:[NSNumber numberWithBool:YES]];
      [issue setPurchased:[NSNumber numberWithBool:NO]];
      [self.managedObjectContext saveToPersistentStore:nil];
   }
}

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

...

case NSFetchedResultsChangeUpdate:

                             [self.tableView deleteRowsAtIndexPaths:@[indexPath]
                              withRowAnimation:UITableViewRowAnimationAutomatic];
        break;

NSFetchedResultsControllerDelegate

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
// The fetch controller has sent all current change notifications, so tell the table view to process all updates.
  [self.tableView endUpdates];
}

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
    // The fetch controller is about to start sending change notifications, so prepare the table view for updates.
    [self.tableView beginUpdates];
}

Error message

CoreData:错误:严重的应用程序错误 . 在调用-controllerDidChangeContent:期间,从NSFetchedResultsController的委托中捕获到异常 . 无效更新:第0节中的行数无效 . 更新(5)后现有部分中包含的行数必须等于更新前该部分中包含的行数(4),加上或减去数字从该部分插入或删除的行(0已插入,1已删除)和加或减移入或移出该部分的行数(0移入,0移出) . 用户信息(null)

2 回答

  • 4

    在您提供给FRC的获取请求中,将此布尔值包含在谓词中 . 例如, [NSPredicate predicateWithFormat:@"shouldDisplay = YES"] . 然后,只要你想删除特定对象,只需将你的shouldDisplay(或你称之为的任何东西)设置为NO,然后你将收到 controller: didChangeObject: 的一个带有 NSFetchedResultsChangeDelete 更改类型的FRC委托回调 . 在此回调中,您将执行以下操作 .

    NSIndexPath *indexPath = [controller indexPathOfObject:anObject];
    [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
    

    您的对象将保留在核心数据中,但由于您对布尔标志的谓词,它将从此特定表视图中过滤掉 .

    编辑:您还需要实现两个FRC委托方法,以通知您的表视图开始和结束更新 . 这将纠正您收到的错误 . 像这样:

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

    我无法让Pat Goley的解决方案起作用,尽管我可能没有正确实现它 . 经过一些实验,我提出的解决方案包含在一个回调方法中:

    override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
        if editingStyle != .Delete { return }
        let obj = fetchedResultsController.objectAtIndexPath(indexPath) as! Entity
        obj.needsDeletion = true
        try! managedObjectContext.save()
        try! fetchedResultsController.performFetch()
        tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
    }
    

    这样做的缺点是必须调用 performFetch() ,但没有它,'s crash city. For very large recordsets, an approach similar to Pat'可能是最好的 .

相关问题