Dispatch.main.async invalid number of rows in section - ios

I'm having an issue when I check off my task to quickly, which makes the app crash and gives me 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 (7) 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).'
Code when radiobutton tapped
func RadioTapped(_ cell: TableViewCell) {
if let indexPath = tableView.indexPath(for: cell) {
// Removes task from coreData
let task = self.tasks[indexPath.row]
self.context.delete(task)
do {
self.tasks = try self.context.fetch(TodayTask.fetchRequest())
(UIApplication.shared.delegate as! AppDelegate).saveContext()
// Animate the removal of task cell
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(800),execute: {
self.tableView.deleteRows(at: [indexPath], with: .fade)
})
} catch {
print("Fetching failed")
}
}
}

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 (7) 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).'
This crash means when you are deleting your table row. You are not updating your arrayCount for instance you have defined 8 inside your numberOfRowsInSection method then before you delete the row you will also need to update the rows count based on the rows you want to delete. Otherwise when your deleteRows will called it will also called the numberOfRowsInSection method and there count will mismatch and it will crash.

Related

Invalid number of rows in section while trying to reload using reloadsections

I have two sections in the tableview.
Rows in section 0 would change when receiving remote notification (insert) or an expired timer (delete).
Section 1 would always have 8 rows and would change when user refresh, all the 8 items would be changed.
I am trying to reload the entire section 0 after the dateset has changed (use refreshed) using.
self.candidates.remoteAll()
for object in json {
let candidate = Candidate(/* Some data */)
self.candidates.append(candidate!)
}
self.tableView.reloadSections(IndexSet(integer: 1), with: .automatic)
and it somehow throws
Fatal Exception: NSInternalInconsistencyExceptionInvalid 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 (0), 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).
The number of inconsistent rows are not fixed, sometimes there are 2 before the update and 1 after, sometimes is 0 before and 1 after the update. My guess is that section 0 was inserting or delete rows while user trying to refresh section 1.
But I was trying to refresh section 1, section 0 should do no effect whether or not it has a consistent number of rows. Where am I doing wrong? Thank you.
Update
Here is numberOfRowsInSection
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch section {
case 0:
if let invitations = self.invitations {
return invitations.count
}
return 0
case 1:
return self.candidates.count
default: return 0
}
}
I am using Realm Result on section 0, and Array on section 1.
I think that in this line of code should be: self.candidates.removeAll()

Error deleting a section on UICollectionView

I have 3 sections that are populated by an array of arrays. Each section has a header and a button that deletes the current section. When I tap the delete button I get the following Error:
Error:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of items in section 0. The number of items contained in an existing section after the update (8) must be equal to the number of items contained in that section before the update (3), plus or minus the number of items inserted or deleted from that section (0 inserted, 0 deleted) and plus or minus the number of items moved into or out of that section (0 moved in, 0 moved out).'
This is the code for the delete function
#IBAction func deleteSection(_ sender: UIButton) {
// grab the tag representign the section
let section = sender.tag
// Update data model
all.remove(at: section)
// reload data to reflect section change
// ignored due to delete sections
photosCollection?.performBatchUpdates({
self.photosCollection?.deleteSections(NSIndexSet(index: section) as IndexSet)
}, completion: { (finished) in
if finished {
self.photosCollection?.reloadData()
}
})
}
all is my array of arrays.

FirebaseTableViewDataSource crashes on user signout and signin

My app has a UITableViewController which uses a FirebaseTableViewDataSource (from FirebaseUI). The table shows the user's bookmarked posts correctly, but when I log that user off, and log another user in, the app crashes with the following message:
* 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 (2), 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 suspect the problem is related to how FirebaseUI updates the content of the tableView. I've being debugging this for the past 4 days; searched the SO questions; read the relevant docs but none mentions this unique issue. Any help will be much appreciated.
The Details (Sorry it's actually long)
This is my database structure:
|
+-posts
| |
| +-$postid
| |
| +-/* properties of a post: title, text, etc */
|
+-users
|
+-$userid
|
+-bookmarks
|
+-post1: true
|
+-post2: true
I am using FirebaseUI to show a user his/her bookmarks by passing the users/$userid/bookmarks ref to FirebaseTableViewDataSource as a query. Then for each key, I observe a single value event on posts/$postid in order to retrieve the post details...code below:
self.authStateListenerHandle = FIRAuth.auth()?.addStateDidChangeListener { auth, user in
guard let user = user else {
return
}
self.query = FIRDatabase.database().reference().child("users").child(user.uid).child("bookmarks")
self.tableViewDataSource = FirebaseTableViewDataSource(query: self.query!, view: self.tableView, populateCell: { (tableView, indexPath, snapshot) -> UITableViewCell in
if snapshot.exists() {
let postRef = FIRDatabase.database().reference().child("posts").child(snapshot.key)
let cell = tableView.dequeueReusableCell(withIdentifier: BookmarksVC.reuseIdentifier, for: indexPath) as! MiniTableCell
postRef.observeSingleEvent(of: .value, with: { (snapshot) in
if snapshot.exists() {
let post = Event(snapshot: snapshot)!
let postVM = EventViewModel(post: post)
cell.populateCellWithEvent(postVM)
cell.delegate = self
}
})
return cell
}
else {
return UITableViewCell()
}
})
self.tableView.dataSource = self.tableViewDataSource
}
I put the above code in viewDidAppear and then remove the authStateListenerHandle in viewWillDisappear like so
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if let handle = self.authStateListenerHandle {
FIRAuth.auth()?.removeStateDidChangeListener(handle)
}
}
Almost everything works fine except, when I am viewing the bookmarks for a user, then log out and log back in, the app crashes with the message
* 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 (2), 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).'
*
In the viewWillDisappear set the self.tableViewDataSource = nil. So, that you don't update the dataSource improperly.

CollectionView.DeleteItems throws exception NSInternalInconsistencyException

I'm getting this exception when I try to call DeleteItems on my UICollectionView. I've googled around and most people are saying they solve this by NOT calling ReloadData on the CollectionView after they call DeleteItems, but I know I'm not calling that. I even overrode it and put a break point on ReloadData and confirmed that it's not getting called.
this.InvokeOnMainThread(() =>
{
CollectionView.DeleteItems (new NSIndexPath [] { indexPath });
});
Objective-C exception thrown. Name: NSInternalInconsistencyException Reason: Invalid update: invalid number of items in section 0. The number of items contained in an existing section after the update (5) must be equal to the number of items contained in that section before the update (5), plus or minus the number of items inserted or deleted from that section (0 inserted, 1 deleted) and plus or minus the number of items moved into or out of that section (0 moved in, 0 moved out).
Looks like I needed to update my list that was tied to my datasource BEFORE calling DeleteItems:
this.InvokeOnMainThread(() =>
{
this.MyList.RemoveAt(indexPath.Row);
CollectionView.DeleteItems (new NSIndexPath [] { indexPath });
});

Adding row to Static UITableView: Invalid update: invalid number of rows in section 1

I'm trying to programatically insert a new row between two existing rows in my static UITableView, but it crashes saying:
'Invalid update: invalid number of rows in section 1. The number of
rows contained in an existing section after the update (6) must be
equal to the number of rows contained in that section before the
update (6), 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).'
This is the code I'm using to add the new row
if (indexPath.section == 1 && indexPath.row == 3) {
// If this is the first subtask we want it to appear under Sub Tasks
if (subTaskRow.count == 0) {
tableView.insertRowsAtIndexPaths([NSIndexPath(forRow: 5, inSection: 1)], withRowAnimation: .Automatic)
// Added the first subtask
subTaskRow.addObject(5)
tableView.reloadData()
// Other sub tasks should appear below previous sub tasks
} else {
let row = (subTaskRow.lastObject as! Int) + 1
tableView.insertRowsAtIndexPaths([NSIndexPath(forRow: row, inSection: 1)], withRowAnimation: .Automatic)
// Keep track of subsequent subtasks
subTaskRow.addObject(row)
tableView.reloadData()
}
}

Resources