I want to delete a row with animation in my table view controller.
I use the following code:
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if (editingStyle == .Delete) {
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
let LM_ITEM = lebensmittel[indexPath.row]
managedObjectContext?.deleteObject(lebensmittel[indexPath.row])
self.DatenAbrufen()
}
}
but after press on delete, I get this error:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (1) must be equal to the number of rows contained in that section before the update (1), 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).'
*** First throw call stack:
(0x1856382d8 0x1973040e4 0x185638198 0x1864eced4 0x18a296e5c 0x10010e278 0x10010ef9c 0x18a2b0ea4 0x18a3a6880 0x18a0e5398 0x18a0ce474 0x18a0e4d34 0x18a0a3f54 0x18a0de82c 0x18a0ddee4 0x18a0b1120 0x18a3522b8 0x18a0af634 0x1855f0240 0x1855ef4e4 0x1855ed594 0x1855192d4 0x18ef6f6fc 0x18a116f40 0x100134420 0x1979aea08)
libc++abi.dylib: terminating with uncaught exception of type NSException
You need to update your model before call tableView.deleteRowsAtIndexPaths(..)
like this,
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if (editingStyle == .Delete) {
let LM_ITEM = lebensmittel[indexPath.row]
managedObjectContext?.deleteObject(lebensmittel[indexPath.row])
self.DatenAbrufen()
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
}
}
Swift 5
tableView.deleteRows(at: [indexPath], with: .automatic)
Use this for Swift 4
tableView.deleteRows(at: [indexPath], with: UITableViewRowAnimation.automatic)
it will delete the tableView row with animation similar to the iPhone messaging application.
Swift 4.2
tableView.deleteRows(at: [IndexPath(row: 0, section: 0)], with: .automatic)
Try the following:
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if (editingStyle == .Delete) {
let LM_ITEM = lebensmittel[indexPath.row]
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
managedObjectContext?.deleteObject(LM_ITEM)
self.DatenAbrufen()
}
}
Related
I have a tableview. The tableview cell contains images, labels. In this cell I have a button to delete the row. I want to animate the cell during deletion(ex. tinder like left or right swipe) or any animation to make the app actractive. How to do this type of animation. Or any recommended library ?
UITableViewCellEditingStyle will do the job for you for i.e
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
//do your necessary operations here
//reload your UITableView here
}
}
Swipe right to left to see the animation.
Typical Animation for your case :
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
// your code
tableView.deleteRows(at: [indexPath], with: .automatic)
// your code
}
}
Alternate Way for custom Animation (Updated):
tableView.beginUpdates()
tableView.deleteRows(at: [indexPath], with: .top) // Check (.)after for available animation example comment out below -
//tableView.deleteRowsAtIndexPaths([YourIndexPathYouWantToDeleteFrom], with: .left)
//tableView.deleteRowsAtIndexPaths([YourIndexPathYouWantToDeleteFrom], with: .right)
//tableView.deleteRowsAtIndexPaths([YourIndexPathYouWantToDeleteFrom], with: .up)
//tableView.deleteRowsAtIndexPaths([YourIndexPathYouWantToDeleteFrom], with: .down)
//tableView.deleteRowsAtIndexPaths([YourIndexPathYouWantToDeleteFrom], with: .fade)
//tableView.deleteRowsAtIndexPaths([YourIndexPathYouWantToDeleteFrom], with: .middle)
//tableView.deleteRowsAtIndexPaths([YourIndexPathYouWantToDeleteFrom], with: .bottom)
tableView.endUpdates()
Sorry for the bad title, and I feel really dumb for asking this question.
I'm deleting a cell from my table and the first block of code runs just perfect, but when shortening the line by creating a variable the code crashes. Why?
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
emojisByCategories[indexPath.section].remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .automatic)
}
}
This small change will cause a "libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)" error
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
var emojis = emojisByCategories[indexPath.section]
emojis.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .automatic)
}
}
Build on Xcode Version 9.0 (9A235)
You have an array of arrays. Array in Swift is a struct which is a value type. When you assign an array to another variable, you are actually creating a copy of the array.
When you do:
var emojis = emojisByCategories[indexPath.section]
emojis.remove(at: indexPath.row)
you are modifying the copy in emojis. Nothing in emojisByCategories is actually being changed as a result of this code.
So now you tell the table view that a row has been deleted but your data source hasn't actually changed at all so you get the crash telling you about an invalid number of rows in a section.
The line:
emojisByCategories[indexPath.section].remove(at: indexPath.row)
doesn't have the same problem because you are not making a copy of any array and the values in emojisByCategories are being updated as expected.
You can make your second set of code work by adding a third line:
var emojis = emojisByCategories[indexPath.section]
emojis.remove(at: indexPath.row)
emojisByCategories[indexPath.section] = emojis
That 3rd line updates emojisByCategories with the updated emojis array so now your code won't crash.
I'm following this answer to get that nice faded deleted cell. Currently when I swipe to delete, it's sharp, sudden and ugly. Other apps has that nice fade when cell is deleted.
In my app, the cell is not really deleted, the data is removed:
Swift 3, func editingStyle:
let tableSection = sections[sortedSections[indexPath.section]]
let tableItem = tableSection![indexPath.row]
// Removes item from array:
self.incomesDictionary.removeValue(forKey: tableItem.incomeId)
// Reloading the table data:
self.tableView.reloadData()
When I add self.tableView.deleteRows(at: [indexPath], with: .fade) above the ...reloadData() I get an error:
terminating with uncaught exception of type NSException
If I update the function with tableSection?.remove(at: indexPath.row), it still crashes. Any tips to get that smooth effect?
Edit:
I have a programmatically grouped cell and the error I got, after adding the .fade is:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'attempt to delete row 0 from section 0, but there are only 0 sections before the update'
Swift 5.0
https://www.hackingwithswift.com/example-code/uikit/how-to-swipe-to-delete-uitableviewcells
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
self.myArray.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade)
}
}
Try this:
self.tableView.beginUpdates()
self.tableView.deleteRows(at: [indexPath], with: .fade)
self.tableView.endUpdates()
This will prepare the tableView for your animation
I'm trying to add functionality so the user can delete a table cell. However, this table cell is populated using a dictionary so I'm getting an error message: "cannot invoke 'removeAtIndex' with an argument list of type {index: Int)
Here's my code:
var titles = [Int: String]()
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == UITableViewCellEditingStyle.Delete {
titles.removeAtIndex(index: indexPath.row)
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
}
}
You need to call removeValueForKey method, because you use Int as keys. The
An you need to add beginUpdates and endUpdates method calls as well to perform the animations.
See the code below:
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == UITableViewCellEditingStyle.Delete {
table.beginUpdates()
titles.removeValueForKey(index: indexPath.row)
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
table.endUpdates()
}
}
Note: in such a case, consider using Array instead of Dictionary? You don't actually need dictionary since it will be indexed from row 0 to row count-1, right?
I am trying to swipe to delete cells from my tableview and every time I attempt to do so I get an error.
This is my code for the actual deletion
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
// Delete the row from the data source
self.tableView.beginUpdates()
self.feedData.removeObjectAtIndex(indexPath.row) // also remove an array object if exists.
self.tableView.deleteRowsAtIndexPaths(NSArray(object: NSIndexPath(forRow: indexPath.row, inSection: 1)) as [AnyObject], withRowAnimation: UITableViewRowAnimation.Left)
// self.tableView.deleteRowsAtIndexPaths(NSArray(object: NSIndexPath(forRow: indexPath.row, inSection: 1)) as [AnyObject], withRowAnimation: UITableViewRowAnimation.Left)
self.tableView.endUpdates()
} 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
}
}
And this is what I am returning in my sections
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Potentially incomplete method implementation.
// Return the number of sections.
return 1
}
I am a beginner so bear with me :)
You need to put the following two functions to handle swipe deletion:
func tableView(tableView: UITableView!, canEditRowAtIndexPath indexPath: NSIndexPath!) -> Bool {
return true
}
func tableView(tableView: UITableView!, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath!) {
if (editingStyle == .Delete) {
// handle delete (by removing the data from your array and updating the tableview)
self.tableView.beginUpdates()
self.feedData.removeObjectAtIndex(indexPath.row) // also remove an array object if exists.
self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Left)
self.tableView.endUpdates()
}
The function tableView(_:canEditRowAtIndexPath:) according to Apple:
Permits the data source to exclude individual rows from being treated as editable. Editable rows display the insertion or deletion control in their cells. If this method is not implemented, all rows are assumed to be editable. Rows that are not editable ignore the editingStyle property of a UITableViewCell object and do no indentation for the deletion or insertion control. Rows that are editable, but that do not want to have an insertion or remove control shown, can return UITableViewCellEditingStyleNone from the tableView:editingStyleForRowAtIndexPath: delegate method.
I hope this help you.