简体   繁体   English

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

[英]How to swipe delete core data tableview in Swift 2.0

I have a table view within a VC. 我在VC中有一个表格视图。 It is populated from a core data object using the following code: 使用以下代码从核心数据对象填充它:

// 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)
    }
}   

Then the table view is populated with this specific fruit data. 然后,使用此特定水果数据填充表格视图。 I have got this method for deletion of the Fruits from the table 我有这种方法可以从桌子上删除水果

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()
    }
}

This instead just crashes the app every time I try to delete the Fruits. 相反,每次我尝试删除Fruits时,这只会使应用程序崩溃。

'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (5) must be equal to the number of rows contained in that section before the update (5), plus or minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).' 'NSInternalInconsistencyException',原因:'无效更新:第0节中的行数无效。更新(5)之后现有节中包含的行数必须等于更新前该节中包含的行数(5 ),加上或减去从该部分插入或删除的行数(已插入0,已删除1),加上或减去移入或移出该部分的行数(0移入,0移出)。

I am suspecting that there is some issue with the fact that I am using an NSArray as opposed to an NSMutableArray . 我怀疑我使用NSArray而不是NSMutableArray的事实存在一些问题。

How can I fix this issue? 如何解决此问题?

Thanks in advance. 提前致谢。

First of all use a Swift array rather than a Foundation array 首先使用Swift数组而不是Foundation数组

var allFruits = [NSManagedObject]()

This avoids a lot of type casting. 这避免了很多类型转换。

To keep Core Data and the table view in sync you have to delete the object in Core Data and in the model. 要使Core Data和表格视图保持同步,您必须删除Core Data 模型中的对象。 The solution to completely reload both the model and the view is very expensive and not needed at all. 完全重新加载模型和视图的解决方案非常昂贵,根本不需要。

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 includes updating the UI so reloading the table view is not needed. deleteRowsAtIndexPaths包括更新UI,因此不需要重新加载表视图。

If the model of the table view is NSManagedObject it's recommended to use NSFetchedResultsController 如果表视图的模型为NSManagedObject则建议使用NSFetchedResultsController

You should update data source before delete. 您应该在删除之前更新数据源。 Like this: 像这样:

     //Reload the fruits
     self.loadFruits()

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

And if you're sure there's no other changes,it's no need to reload data because this costs a lot. 而且,如果您确定没有其他更改,则无需重新加载数据,因为这会花费很多。

I fixed my code by simply changing this method: 我通过简单地更改此方法来修复代码:

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


        }
    }

This successfully deletes the object from the core data as well as updating the table view. 这样可以成功地从核心数据中删除对象,并更新表视图。

Updated for Swift 3 Xcode 8 iOS 10 已针对Swift 3 Xcode 8 iOS 10更新

The following code snippet adds a 'swipe to delete' to your Table Row, and also saves the changes to CoreData. 以下代码段向您的表格行添加了“删除删除”,并将更改保存到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.
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM