问题
So I have my tableview when I re-order my rows it updates the tableview and everything but it isn't saving to core data.
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let movedCampSites = itemName[sourceIndexPath.item]
itemName.remove(at: sourceIndexPath.item)
itemName.insert(movedCampSites, at: destinationIndexPath.item)
context.delete(itemName[sourceIndexPath.row])
context.insert(itemName[destinationIndexPath.row])
do
{
try context.save()
}
catch
{
print("Could not move rows")
}
}
Everything works up till context.insert(itemName[destinationIndexPath.row]) for example if I comment that out and run it, it will move the rows and delete the row and save to core data, but the context.insert doesn't save the new row position. For some reason it is running my catch block as I am getting the error Could not move rows.
Here is some of the error that is in the console.
2018-07-22 09:27:01.884925-0700 Search Bar Core Data[67957:5383630] [error] error: (1555) UNIQUE constraint failed: ZTITLE.Z_PK CoreData: error: (1555) UNIQUE constraint failed: ZTITLE.Z_PK Could not move rows
Thanks in advance.
回答1:
Here is my take on this issue:
Like 'vadian' said, when you create an object you add a property for the array that appends to the Core Data, like this,
var itemsArray: [NSManagedObject] = []
save(sortOrder: itemsArray.count, item: itemTextField.text!) //Calling the save method wherever you need to, catching for example a UITextField user input
private func save(sortOrder: Int, item: String) {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
let context = appDelegate.persistentContainer.viewContext
guard let entity = NSEntityDescription.entity(forEntityName: "CoreDataBaseName", in: context) else { return }
let itemManagedObject = NSManagedObject(entity: entity, insertInto: context)
itemManagedObject.setValue(sortOrder, forKeyPath: "sortOrder")
itemManagedObject.setValue(item, forKeyPath: "item")
do {
try context.save()
itemsArray.append(itemManagedObject)
} catch let error as NSError {
print("Could not save item to Core Data: \(error)")
}
}
Then we come to the tableView's moveRowAt method,
override func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
let context = appDelegate.persistentContainer.viewContext
let movedItem = itemsArray[sourceIndexPath.row]
itemsArray.remove(at: sourceIndexPath.row)
itemsArray.insert(movedItem, at: destinationIndexPath.row)
//This 'for-in loop' is at the heart of the solution
for (i, item) in itemsArray.enumerated() {
item.setValue(i, forKey: "sortOrder")
}
do {
try context.save()
} catch let error as NSError {
print("Could not save/persist Core Data items in moveRowAt: \(error)")
}
}
... And at the end of everything we fetch the rearranged order with,
private func fetch() {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
let context = appDelegate.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "CoreDataBaseName")
let sortDescriptor = NSSortDescriptor(key: "sortOrder", ascending: true)
fetchRequest.sortDescriptors = [sortDescriptor]
do {
itemsArray = try context.fetch(fetchRequest)
} catch let error as NSError {
print("Could not fetch Core Data entities: \(error)")
}
}
There's a million different ways that you can improve this idea (which is always welcome), but this is a pedagogical example of a solution.
I hope it can help somebody out there!
来源:https://stackoverflow.com/questions/51467055/how-to-save-re-ordered-tableview-cells-to-core-data