I'm using Xcode 8 and swift 3.
I'm getting an assertion failure when I try to delete a row from a UITableView.
Assertion failure in -[UITableView _endCellAnimationsWithContext:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-3599.5/UITableView.m:1610
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 (25) must be equal to the number of rows contained in that section before the update (25), 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).'
Code:
// create a cell for each table view row
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// create a new cell if needed or reuse an old one
let cell:UserCell = self.tableView.dequeueReusableCell(withIdentifier: "tblCell") as! UserCell!
cell.titleLabel.text = self.animals[(indexPath as NSIndexPath).row]
cell.btnDelete.addTarget(self, action:#selector(ViewController.buttonClicked(sender:)), for: UIControlEvents.touchUpInside);
return cell
}
func buttonClicked(sender:UIButton) {
if let superview = sender.superview {
if let cell = superview.superview as? UserCell {
if let indexPath = self.tableView.indexPath(for: cell){
print("row = ",indexPath.row)
self.tableView.beginUpdates()
self.tableView.deleteRows(at: [indexPath], with: .left)
self.tableView.endUpdates()
self.animals.remove(at:indexPath.row)
}
}
}
}
I have just started learning swift so please help me.
try to move self.animals.remove(at:indexPath.row) before self.tableView.endUpdates() and after self.tableView.beginUpdates() I think that might solve your problem.
Related
When I remove an object from a list and try to add a new one in I get this error
2020-01-24 14:40:26.692343+1300 HappyDays[25416:1017241] *** 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 (3) must be equal to the number of rows contained in that section before the update (0), plus or minus the number of rows inserted or deleted from that section (1 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'
I see other issues similar to this but I've tried implementing those solutions . (Similar issue , another similar issue)
Sections of my code:
Selecting the cell to delete if from the table
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
activeObjectives.actives.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .left)
}
Adding a new object to the table by tapping a button
#IBAction func getGoals(_ sender: UIButton) {
let newRowIndex = activeObjectives.actives.count
activeObjectives.setRandomGoalToActive(allObjectiveList: allGoalsArray)
addActiveGoalToactiveObjectives()
let indexPath = IndexPath(row: newRowIndex, section: 0)
let indexPaths = [indexPath]
activeGoalDisplay.insertRows(at: indexPaths, with: .automatic)
}
In case it's also needed, here is my addActiveGoalToactiveObjectives function called in the above
func addActiveGoalToactiveObjectives() {
for goal in allGoalsArray.goalsList {
if goal.isActive == true && activeObjectives.actives.contains(goal) == false {
activeObjectives.actives.append(goal)
}
}
}
Thanks in advance, any help is greatly appreciated
I found the issue. I wasn't setting an object value to false when removing it from the list. Now when I remove them I set the object to inactive.
activeObjectives.actives[indexPath.row].setInactive()
activeObjectives.actives.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .left)
}```
Following is my code to add section header view cell
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let cell = tableView.dequeueReusableCell(withIdentifier: "menuHeaderTableViewCellID") as! MenuHeaderTableViewCell
cell.foodMenuItems = menuResult?.foodMenuItems?[section]
cell.setParentUI()
cell.expandCollapseClicked = {
[weak self]
(postiton) in
let isCollapsed = self?.menuResult?.foodMenuItems?[postiton].isCollapsed ?? false
self?.menuResult?.foodMenuItems?[postiton].isCollapsed = !isCollapsed
self?.tableViewMenu?.beginUpdates()
self?.tableViewMenu?.reloadSections([section], with: .fade)
self?.tableViewMenu?.endUpdates()
}
return cell
}
Following is code for count in each row and section
func numberOfSections(in tableView: UITableView) -> Int {
return (menuResult?.foodMenuItems?.count) ?? 0
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let rowCount = menuResult?.foodMenuItems?[section].items?.count ?? 0
let isCollpased = menuResult?.foodMenuItems?[section].isCollapsed ?? false
return isCollpased ? 0 : rowCount
}
Following is code inside header view cell
#IBAction func expandCollapseClicked(_ sender: UIButton) {
guard let superView = self.superview as? UITableView else {
return
}
expandCollapseClicked?(superView.indexPath(for: self)?.section ?? 0)
}
I am facing issue on collapsing first section my header disappears and when I try to collapase other section getting following exception how to fix this?
*** 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 (0) must be equal to the number of rows contained in that section before the update (25), plus or minus the number of rows inserted or deleted from that section (0 inserted, 0 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:
Problem may be in :
Avoid dequeueReusableCell. Try to use UIView with label and button.
expandCollapseClicked = {...}
should be called by UIButton. as it's sender is UIButton. Try to use:
view.button.expandCollapseClicked = {...}
Hope this will work.
Hello I am using SwipeCellKit for my UITableView. I want to do the deletion when swipe the cell. This is how I handle the delete part. self.deleteLeave() is calling to web service and delete the selected leave entry in the server side. Then if its successfully deleted in the server side I want to delete that object from the current array and update my UITableView. But my problem is when I swipe and click on the delete button or else dragged it for some extent app is crashing by giving an exception.
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).'
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath, for orientation: SwipeActionsOrientation) -> [SwipeAction]? {
guard orientation == .right else { return nil }
let deleteAction = SwipeAction(style: .destructive, title: "Delete") { action, indexPath in
// handle action by updating model with deletion
self.com.showProgress()
let dict=self.arrayPendings[indexPath.row] as! [String:Any]
if let reid=dict["RequestId"] as? Int
{
self.selectedReqID=String(reid)
}
self.deleteLeave(){ (status) in
if(status)
{
let delete = SwipeAction(style: .destructive, title: nil) { action, indexPath in
self.com.removeProgress()
self.arrayPendings.remove(at: indexPath.row)
self.tblPendingLeaves.beginUpdates()
//self.tblPendingLeaves.insertRows(at: [IndexPath(row: 0, section: 1)], with: .automatic)
self.tblPendingLeaves.deleteRows(at: [indexPath], with: .fade)
action.fulfill(with: .delete)
self.tblPendingLeaves.endUpdates()
}
}
}
}
// customize the action appearance
deleteAction.image = UIImage(named: "Delete")
return [deleteAction]
}
I have the same problem.
When i call delete it crash and show me the same error.
What i dis is:
delete data from tableView then delete the same data from myDataSource(for example: remove data from array). This will handle your case but it will not refresh the table. (If you close and reopen the project it will delete it from table view).
So check the connections between your data and your table.
I am experiencing a crash when I delete a row.
// Updating my data model
....
// apply the updates
self.tableView.beginUpdates()
self.tableView.deleteRows(at: indexPathsToDelete, with: .automatic)
self.tableView.endUpdates()
Steps to reproduce
- Add rows
- Delete rows, specifically making sure there's some rows outside the current screen (that will then be in screen when the deletion is successful
- Repeat until crash occurs
It doesn't always happen so my best guess is that it will happen only when the cells it's trying to load get recycled
This is in 10.0 simulator with Xcode 8.0
*** Assertion failure in -[UITableView _updateWithItems:updateSupport:],
/BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-3599.6/UITableView.m:3149
Missing cell for newly visible row 2
(null)
code for cellForRowAt
if isMultipe{
let cell = tableView.dequeueReusableCell(withIdentifier: DetailsTableViewCell.defaultIdentifier, for: indexPath) as! DetailsTableViewCell
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: DetailsMultipleTableViewCell.defaultIdentifier, for: indexPath) as! DetailsMultipleTableViewCell
return cell
}
the same bug reported here : https://forums.developer.apple.com/thread/49676
I had the same problem and I found out that UITableView has serious problems with animating insert/update/delete rows when section headers are variable height. Just convert the height to some constant and try it again.
This actually means deleting estimatedSectionHeaderHeight.
In my case it was crashing when cells have used autolayout for calculating it's height. So, the only guaranteed solution is use manual calculating heights. (what is actually sad..)
In my case I had this issue just for inserting the first row to an empty section, so I tried to fix it like this:
self.array.append(item)
if self.array.count > 1 {
self.tableView.beginUpdates()
self.tableView.insertRows(at: indexPathes, with: .top)
self.tableView.endUpdates()
} else {
self.tableView.reloadSections([1], with: .fade)
}
This problem happened to me when I had cells with different sizes. My code:
tableView.estimatedRowHeight = 150
tableView.rowHeight = UITableViewAutomaticDimension
During moving/inserting/deleting, app was crashing with "Missing cell for newly visible row" message. So I removed this line:
tableView.estimatedRowHeight = 150
and implement delegate method in which returned separate estimated height for each row.
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {}
Hope it will help someone.
Remove indexPath in tableView.dequeueReusableCell
if isMultipe{
let cell = tableView.dequeueReusableCell(withIdentifier: DetailsTableViewCell.defaultIdentifier) as! DetailsTableViewCell
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: DetailsMultipleTableViewCell.defaultIdentifier) as! DetailsMultipleTableViewCell
return cell
}
I had a similar problem.
emrekyv suggested to delete estimatedSectionHeaderHeight but I have a table with one seaction and no header and no footer.
Expanding his idea and setting estimatedRowHeight to 0 (= not automatic) fixed the problem.
So the rule is:
Do not estimate any height when updating a UITableView.
In my case this happened when I forgot to call super.prepareForReuse() in my custom subclass.
See https://developer.apple.com/documentation/uikit/uitableviewcell/1623223-prepareforreuse:
If you override this method, you must be sure to invoke the superclass
implementation.
okay im making an app where you add items to a cart and it updates as you add. i do all the adding fine, but i cant get deleting to work. in the cart cell i would need to remove from 3 arrays, but that doesn't seem to be the problem because i keep getting 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).'"
i'm not really sure what i'm doing wrong here. i've followed a few tutorials and they all seem to be doing the same thing. any help is appreciated thanks in advance.
heres some of my code:
//declaring arrays to show in cell
var cartKeys = [String]()
var cartValues = [String]()
var deets = [[String]]()
var count = 0
//populating arrays from original arrays
func populateCart(){
for (key,value) in MenuStore.shared.cart {
self.cartKeys.append(key)
self.cartValues.append(value)
}
for i in MenuStore.shared.cartAndItems{
for (k,v) in i {
deets.append(v)
}
}
print("DEETS \(deets)")
for c in cartView.visibleCells {
count += 1
}
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
switch tableView{
case cartView:
if editingStyle == .delete{
let index = indexPath.row
print(index)
cartKeys.remove(at: index)
cartValues.remove(at: index)
deets.remove(at: index)
tableView.deleteRows(at: [indexPath], with: .automatic)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch tableView{
case cartView:
let cartCell = tableView.dequeueReusableCell(withIdentifier: "cartCell", for: indexPath) as? CartCell
cartCell?.cartTitle.text = cartKeys[(indexPath as NSIndexPath).row]
cartCell?.cartPrice.text = cartValues[(indexPath as NSIndexPath).row]
cartCell?.cartDetails.text = deets[count].joined(separator: ", ")
return cartCell!
ps. if anyone wants to help with replacing the visible cells call thatd be great. id like to loop through all the cells even if their not visible on the screen.