如何在 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 中滑动删除核心数据表视图的主要内容,如果未能解决你的问题,请参考以下文章