【问题标题】:How to swipe delete core data tableview in Swift 2.0如何在 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 这一事实存在一些问题。

我该如何解决这个问题?

提前致谢。

【问题讨论】:

    标签: ios swift uitableview core-data


    【解决方案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.
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2021-03-06
      • 1970-01-01
      • 2023-03-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-06
      • 1970-01-01
      相关资源
      最近更新 更多