I make a table view on my application, I want to add option that could the user delete the row in tableview.
I'm using this func
h1 is my array string that I put it in tableview.
my error is when I'm try to delete row in func editinstyle
var h1:[String] = ["one","two","three"]
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
h1.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = self.tableView.dequeueReusableCell(withIdentifier: "cell3", for: indexPath as IndexPath) as! TableView1
cell.information.text = h1[indexPath.row]
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
print("Deleted")
h1.remove(at: indexPath.row) //Remove element from your array
print(h1)
tableView.deleteRows(at: [indexPath], with: .fade)
}
}
when I try to click to Delete it show like this 2020-02-11 20:43:35.803024+0200 TraniersApp[13314:401189] *** 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 (2) must be equal to the number of rows contained in that section before the update (2), 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).'
Does someone know where is the problem?
To define "[indexPath]". It becomes [IndexPath(row: indexPath.row, section: 0)]
tableView.deleteRows(at: [IndexPath(row: indexPath.row, section: 0)], with: .automatic)
or
recall the particular section in the table view also
This will work outside of the function
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath)
Suspect this is a race condition that can be resolved by performing the h1.remove() and tableView.deleteRows() within a transaction (i.e., between tableView.beginUpdates() and tableView.endUpdates()).
tableView.beginUpdates()
h1.remove(at: indexPath.row) //Remove element from your array
tableView.deleteRows(at: [indexPath], with: .fade)
tableView.endUpdates()
Related
I want to delete an item from a table view.
First I added a filePath property on my class (that was missing)
Then I corrected the line of code to find the right filePath
the problem is solved but still I have the wrong file deleted so I check the sync of the arrays.
First, I make sure the table view knows what it shows and it appears the arrays are synced. I debug the code and I find that when I swipe to delete an item the code still deletes another file.
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableOfExpences.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CellOfExpencesTableViewCell
let myOneExpense = self.tableOfExpences[indexPath.row]
if myOneExpense.size != nil {
//Arrangement Of the cell
//allocate the right image for each segment
} else {
cell.nameCellLabel?.text = "No Cost"
}
return cell
}
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
// Delete the row from the data source
self.tableOfExpences.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade)
print("the removed from the table expence is the \(String(describing: tableOfExpences[indexPath.row].expenseID))")
print("We had bought a \(String(describing: tableOfExpences[indexPath.row].note))")
In my case there was a numerous things why the wrong file was deleted but the most tricky(when all the code seemed to be correct) was that first the file must be removed from the directory and then the cell from the table.
So just reversing the order of lines so that first to delete data from the file
try FileManager.default.removeItem(atPath: paths[indexPath.row])
and then to implement the
self.tableOfExpences.remove(at: indexPath.row)
solved the last great problem.
Swift 3.0 iOS 10.x
Using this code to try and delete a row in a table...
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == UITableViewCellEditingStyle.delete {
print("DELETE \(indexPath)")
self.tableView.deleteRows(at: [indexPath], with: UITableViewRowAnimation.automatic)
}
}
This fails with the error message?
2017-05-29 13:36:23.843228+0200[939:576777] *** 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 (9) must be equal to the number of rows contained in that section before the update (9), 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).'
Which sounds fair enough only this is boiler plate code? I am doing little more than clicking on the red button?
Yes, there are 3 rows here... in my code that crashed there were 9.
What have I missed here? Printed out the returned indexPath here and indeed it was wrong, but wait I didn't set it. This method did?
DELETE [0, 3]
You must delete row in your data array before deleting in tableView
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == UITableViewCellEditingStyle.delete {
print("DELETE \(indexPath)")
yourArray.remove(at: indexPath.row) /* delete in data array */
self.tableView.deleteRows(at: [indexPath], with: UITableViewRowAnimation.automatic)
}
}
Swift 3.0 iOS 10.x
Using this code to try and delete a row in a table...
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == UITableViewCellEditingStyle.delete {
print("DELETE \(indexPath)")
self.tableView.deleteRows(at: [indexPath], with: UITableViewRowAnimation.automatic)
}
}
This fails with the error message?
2017-05-29 13:36:23.843228+0200[939:576777] *** 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 (9) must be equal to the number of rows contained in that section before the update (9), 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).'
Which sounds fair enough only this is boiler plate code? I am doing little more than clicking on the red button?
Yes, there are 3 rows here... in my code that crashed there were 9.
What have I missed here? Printed out the returned indexPath here and indeed it was wrong, but wait I didn't set it. This method did?
DELETE [0, 3]
You must delete row in your data array before deleting in tableView
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == UITableViewCellEditingStyle.delete {
print("DELETE \(indexPath)")
yourArray.remove(at: indexPath.row) /* delete in data array */
self.tableView.deleteRows(at: [indexPath], with: UITableViewRowAnimation.automatic)
}
}
I'm trying to let users delete a row from a UITableView that's populated using a NSFetchedResultsController but keep getting a fatal error:
Terminating app due to uncaught exception
'NSInternalInconsistencyException', reason: 'Invalid update: invalid
number of rows in section 1. The number of rows contained in an
existing section after the update (7) must be equal to the number of
rows contained in that section before the update (7), 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).'
I'm deleting the core data entry and then deleting the row in the tableView in my code but still get the error above:
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
self.feedTable.beginUpdates()
let event = self.fetchedResultsController.object(at: indexPath) as Event
self.managedObjectContext.delete(self.fetchedResultsController.object(at: indexPath))
do {
try self.managedObjectContext.save()
} catch {}
self.feedTable.deleteRows(at: [indexPath], with: .automatic)
self.feedTable.endUpdates()
}
}
Can anybody help understand what I'm doing wrong?
If you use a fetched results controller. Only delete the object with
self.managedObjectContext.delete(self.fetchedResultsController.object(at: indexPath))
Try this solution
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
let event = self.fetchedResultsController.object(at: indexPath) as Event
self.managedObjectContext.delete(self.fetchedResultsController.object(at: indexPath))
do {
try self.managedObjectContext.save()
} catch {}
}
}
You don't need beginUpdates and endUpdates
I have an array which populates a table view - myPosts.
The first row of the table view is not part of the array.
Each row is its own section (with its own custom footer)
I am trying to perform a delete with the following code:
func tableView(profileTableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if (editingStyle == UITableViewCellEditingStyle.Delete) {
myPosts?.removeAtIndex(indexPath.section - 1)
profileTableView.beginUpdates()
let indexSet = NSMutableIndexSet()
indexSet.addIndex(indexPath.section - 1)
profileTableView.deleteSections(indexSet, withRowAnimation: UITableViewRowAnimation.Automatic)
profileTableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
profileTableView.endUpdates()
...
WS Call
...
}
}
And the log is reporting the following:
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).'
Obviously the issue is related to 0 moved in, 0 moved out but I don't understand why that is? or what the solution would be?
Number of sections in tableView is as follows:
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
if self.myPosts == nil
{
return 1
}
return self.myPosts!.count + 1
}
Updated the answer for Swift 4.2 and made a few additional tweaks:
func tableView(_ tableView: UITableView,
commit editingStyle: UITableViewCell.EditingStyle,
forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
myPosts?.removeAtIndex(indexPath.section - 1)
let indexSet = IndexSet(arrayLiteral: indexPath.section)
profileTableView.deleteSections(indexSet, with: .automatic)
// Perform any follow up actions here
}
}
The use of beginUpdates() and endUpdates() is not necessary, since you are only doing one action that contains animation. If you are doing 2 or more, than it is worth combining them to get a fluid effect.
Also, this makes use of the Swift 3 classes, by doing away with the NSMutableIndexSet() call, which would require a conversion now to work with the deleteSections() call.
So the answer is just removing the line that deletes the rows.
So the code is here to delete:
func tableView(profileTableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if (editingStyle == UITableViewCellEditingStyle.Delete) {
myPosts?.removeAtIndex(indexPath.section - 1)
profileTableView.beginUpdates()
let indexSet = NSMutableIndexSet()
indexSet.addIndex(indexPath.section - 1)
profileTableView.deleteSections(indexSet, withRowAnimation: UITableViewRowAnimation.Automatic)
// profileTableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
profileTableView.endUpdates()
...
WS Call
...
}
}