删除表格视图中的一行而不删除核心数据实体

Posted

技术标签:

【中文标题】删除表格视图中的一行而不删除核心数据实体【英文标题】:Deleting a row in tableview without deleting Core Data Entity 【发布时间】:2013-12-04 17:24:49 【问题描述】:

我有一个由 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 移出)。与 userInfo (null)

【问题讨论】:

作为一个想法,理论上我可以保留对该数据的引用,删除实体,删除带有动画的行,然后创建已删除的实体并再次保存。 【参考方案1】:

在您向 FRC 提供的获取请求中,将此布尔值包含在您的谓词中。例如,[NSPredicate predicateWithFormat:@"shouldDisplay = YES"]。然后,每当您要删除特定对象时,只需将您的 shouldDisplay(或您所称的任何内容)设置为 NO,您将收到带有 NSFetchedResultsChangeDelete 更改类型的 controller: didChangeObject: 的 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];

【讨论】:

感谢您的建议。你能看看我的编辑吗?我之前和现在都尝试过这种方法,但仍然出现此错误。是否有可能对该布尔标志的更改不会保存到核心数据中? 谢谢。我也有这些方法。我已经在他们身上设置了断点。他们也会被调用。 好的,谢谢您的宝贵时间!我发现了一个问题。我使用带有“错误”谓词的“错误”NSFetchedResultsController(我有几个)。现在,当我移到正确的位置时,一切正常:) 将布尔值添加为谓词会产生错误,因为它在实体中未被识别为键路径。有什么建议么?我已经声明了它并尝试了 [NSPredicate predicateWithFormat: @"%@", shouldDisplay];作为替代方案,但它会使应用程序崩溃。【参考方案2】:

我无法让 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 的方法可能是最好的。

【讨论】:

以上是关于删除表格视图中的一行而不删除核心数据实体的主要内容,如果未能解决你的问题,请参考以下文章

在 iOS7 中使用核心数据删除表格视图中的行的奇怪行为

如何使用tableview删除核心数据中的数据

删除子视图中的核心数据后更新表视图

从 TableView 中的 CoreData 中删除实体时出错

如何从数据数组中删除对象(核心数据)

在表视图中删除核心数据对象