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

时间:2013-12-04 17:24:49

标签: ios uitableview core-data nsfetchedresultscontroller

我有一个由NSFetchedResultsController支持的表视图。 情况如下。 我已经实现了“轻扫删除”一行。调用NSFetchedResultsController的委托方法和表视图的委托方法。但问题是,我不想删除核心数据实体,我只想标记它的布尔标志,因为我在应用程序的其他部分需要这个实体,并希望表视图删除带动画的行。但是,根据错误消息,它与逻辑相反,如果您要更新实体,更新行,而不是删除它。 有没有优雅的方法来实现它?或者唯一的选择是重新加载表格? 实施滑动删除

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

错误消息

  

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

2 个答案:

答案 0 :(得分:4)

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

NSFetchedResultsChangeDelete

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

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

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

答案 1 :(得分: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(),但没有它,它就会崩溃。对于非常大的记录集,类似于Pat的方法可能是最好的。