如何在 Swift 2.0 中滑动删除核心数据表视图

Posted

技术标签:

【中文标题】如何在 Swift 2.0 中滑动删除核心数据表视图【英文标题】:How to swipe delete core data tableview in Swift 2.0 【发布时间】:2016-05-12 03:42:45 【问题描述】:

我在 VC 中有一个表格视图。它是使用以下代码从核心数据对象填充的:

// Variables
var allFruits: NSArray
var managedObjectContext: NSManagedObjectContext
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate

func loadFruits()
    // Try to load all of the Fruits from the core data.
    let fetchRequest = NSFetchRequest()

    let entityDescription = NSEntityDescription.entityForName("Fruit", inManagedObjectContext: self.managedObjectContext)

    fetchRequest.entity = entityDescription
    do
        self.allFruits = try self.managedObjectContext.executeFetchRequest(fetchRequest)

        if self.allFruits.count == 0
            print("No saved Fruits")
        
    
    catch
    
        let fetchError = error as NSError
        print(fetchError)
    
   

然后表格视图将填充这个特定的水果数据。我有这种从表中删除水果的方法

func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) 
    if (editingStyle == UITableViewCellEditingStyle.Delete) 
         // handle delete (by removing the data from your array and updating the tableview)
         managedObjectContext.deleteObject(allFruits[indexPath.row] as! NSManagedObject)

         // Attempt to save the object
         do
             try appDelegate.managedObjectContext.save()
         
             catch let error
             print("Could not save Deletion \(error)")
         

         // Remove the deleted item from the table view
         self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)

         // Reload the fruits
         self.loadFruits()

         // Reload the table view
         tableView.reloadData()
    

每当我尝试删除水果时,这只会使应用程序崩溃。

'NSInternalInconsistencyException',原因:'无效更新:无效 第 0 节中的行数。包含在第 0 节中的行数 更新后的现有节(5)必须等于 更新前该部分中包含的行 (5),加号或减号 从该部分插入或删除的行数(0 插入, 1 已删除)并加上或减去移入或移出的行数 该部分(0 移入,0 移出)。'

我怀疑我使用NSArray 而不是NSMutableArray 这一事实存在一些问题。

我该如何解决这个问题?

提前致谢。

【问题讨论】:

【参考方案1】:

首先使用 Swift 数组而不是 Foundation 数组

var allFruits = [NSManagedObject]()

这避免了很多类型转换。

要使 Core Data 和表视图保持同步,您必须删除 Core Data 中的对象和模型中的。完全重新加载模型和视图的解决方案非常昂贵且根本不需要。

func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) 
  if editingStyle == .Delete 

    let objectToDelete = allFruits[indexPath.row]
    allFruits.removeAtIndex(indexPath.row)
    managedObjectContext.deleteObject(objectToDelete)

    //Attempt to save the object
    do
      try appDelegate.managedObjectContext.save()
      tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
    
    catch let error
      print("Could not save Deletion \(error)")
    
  

deleteRowsAtIndexPaths 包括更新 UI,因此不需要重新加载表格视图。

如果表格视图的模型是NSManagedObject,建议使用NSFetchedResultsController

【讨论】:

但是我有一个代码问题:无法在self.allFruits = try self.managedObjectContext.executeFetchRequest(fetchRequest) 部分中将 [AnyObject] 类型的值分配给 [NSManagedObject] 类型的值 你需要写self.managedObjectContext.executeFetchRequest(fetchRequest) as! [NSManagedObject]【参考方案2】:

您应该在删除之前更新数据源。像这样:

     //Reload the fruits
     self.loadFruits()

     //Remove the deleted item from the table view
     self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)

如果您确定没有其他更改,则无需重新加载数据,因为这会花费很多。

【讨论】:

那我做错了什么?我按照你建议的方式删除它。 @Tirat2131 我对我的错误感到非常抱歉。更新了我的回答,希望对你有所帮助。【参考方案3】:

我通过简单地更改此方法来修复我的代码:

func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) 
        if (editingStyle == UITableViewCellEditingStyle.Delete) 


             // handle delete (by removing the data from your array and updating the tableview)
             managedObjectContext.deleteObject(allFruits[indexPath.row] as! NSManagedObject)

             //Attempt to save the object
             do
             try appDelegate.managedObjectContext.save()
             
             catch let error
             print("Could not save Deletion \(error)")
             

             //Reload the fruits
             self.loadFruits()

             //Reload the table view
             tableView.reloadData()


        
    

这成功地从核心数据中删除了对象并更新了表视图。

【讨论】:

是的,这将起作用,因为您首先更新数据源。【参考方案4】:

为 Swift 3 Xcode 8 iOS 10 更新

以下代码 sn-p 将“滑动删除”添加到您的表格行,并将更改保存到 CoreData。

override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) 
    let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext

    if editingStyle == .delete 
         context.delete(tasks[indexPath.row] as NSManagedObject)
        //objects.remove(at: indexPath.row)
        tableView.deleteRows(at: [indexPath], with: .fade)

        //Save the object
        do
            try (UIApplication.shared.delegate as! AppDelegate).saveContext()
        
        catch let error
            print("Cannot Save: Reason: \(error)")
        

        //Reload your Table Data
        getData()

        //Reload the table view
        tableView.reloadData()

     else if editingStyle == .insert 
        // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
    

【讨论】:

以上是关于如何在 Swift 2.0 中滑动删除核心数据表视图的主要内容,如果未能解决你的问题,请参考以下文章

核心数据和数组 swift 2.0

如何在 swift 3 中从核心数据中删除对象

Swift:如何使用编辑按钮删除并停用滑动删除?

如何在swift 5中实现滑动中的两个垂直按钮以删除

如何从核心数据swift中删除项目3

Swift:UITableView - 滑动删除 - 如何让单元格内容在滑动时不移动