Dispatch.main.asyncAfter() crash app when called before it's finished - ios

so I have an app with radiobuttons to check off tasks, everything's working as expected as long as I let the animation finish but if I press two buttons at the same time I get an error:
libc++abi.dylib: terminating with uncaught exception of type NSException
The Code executed every time a radiobutton is tapped
func RadioTapped(_ cell: TableViewCell) {
if let indexPath = tableView.indexPath(for: cell) {
// Removes task from coreData
let task = self.tasks[indexPath.row]
print(tasks.count)
self.context.delete(task)
print(tasks.count)
(UIApplication.shared.delegate as! AppDelegate).saveContext()
do{
self.tasks = try self.context.fetch(TodayTask.fetchRequest())
// Animates the removal of task cell
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(800),execute: {
self.tableView.beginUpdates()
self.tableView.deleteRows(at: [indexPath], with: .fade)
self.tableView.endUpdates()
})
} catch {
print("Fetching Failed")
}
}
}
Error 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 (11) must be equal to the number of rows contained in that section before the update (13), 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).'

Table row delete operation also requires to delete element of array of table.
According to your code, self.tasks may be an array for your table list.
Delete an element of 'self.tasks' from same indexes, for which you are deleting your rows.
Hint:
// Remove array element
self.tasks.remove(at: <index.row>)
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(800),execute: {
self.tableView.beginUpdates()
self.tableView.deleteRows(at: [indexPath], with: .fade)
self.tableView.endUpdates()
})

Related

NXException when removing and then adding an itme to UITableView

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)
}```

How to delete all rows of section in Swift

I am working on a code where I have to insert & delete all rows on selecting a section.
Below is the code for inserting & deleting
var paths = [IndexPath]()
for row in 0..<(arrayOfSection?.count)! {
let indexPath = IndexPath(row: row, section: selectedIndex!)
paths.append(indexPath)
}
// Toggle collapse
if previousSelectedIndex != nil && previousSelectedIndex == section {
self.arrayOfCategories?.removeAll()
self.catergoryTableView.beginUpdates()
self.catergoryTableView.deleteRows(at: paths, with: .fade)
self.catergoryTableView.endUpdates()
}
else{
self.catergoryTableView.beginUpdates()
self.catergoryTableView.insertRows(at: paths, with: .fade)
self.catergoryTableView.endUpdates()
header.setCollapsed(false)
//scroll
let sectionRect = self.catergoryTableView.rect(forSection: selectedIndex!)
self.catergoryTableView.scrollRectToVisible(sectionRect, animated: true)
}
previousSelectedIndex = selectedIndex
Inserting rows works fine but when I am trying to delete rows from selected section in am getting below error
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'attempt to delete row 9 from section 0 which only contains 0 rows before the update'
What am I doing wrong?
Update your code to delete all row as follows:
self.catergoryTableView.beginUpdates()
self.catergoryTableView.deleteRows(at: paths, with: .fade)
self.catergoryTableView.endUpdates()
self.arrayOfCategories?.removeAll()
Just add first line of code to the last.

SwipeCellKit crash when try to delete

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.

Insert new rows in tableView in iOS

I am writing an iOS app in Swift.
Whenever the page loads it gets the list of movies from server and it populates that list into tableView.
I wrote the code for getting JSON from server in a static library (Objective-C) and am receiving json to app via Notification design pattern.
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(ReceivedNListOfMoviesNotification(_:)), name: Notification.Name(VUSDK.basicNotificationName()), object: nil)
requestForData()
}
func ReceivedNListOfMoviesNotification(_ notification:NSNotification)
{
if let info = notification.userInfo {
basicArray=info["Search"] as! [Any]
if basicArray.count>0 {
tableView.beginUpdates()
self.tableView.insertRows(at: [IndexPath.init(row: self.basicArray.count-1, section: 0)], with: .automatic)
tableView.endUpdates()
}
}
}
But app is crashing:
*** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-3600.7.47/UITableView.m:1737
2017-04-23 13:49:12.562 VUDemo[4835:164247] *** 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 (10) 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).'
Replace
if basicArray.count>0 {
tableView.beginUpdates()
self.tableView.insertRows(at: [IndexPath.init(row: self.basicArray.count-1, section: 0)], with: .automatic)
tableView.endUpdates()
}
with
if !basicArray.isEmpty {
tableView.reloadData()
}
because you are overwriting the entire array rather than adding a single item.

Swift - search controller keeps crashing

I am just starting to learn to swift; I want to add a search bar that allows users to search through the data in my Firebase database. The search bar has added but the code to filter the search result keeps crashing with 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 (0) 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).
The error is pointing to this line
self.tableView.insertRows(at: [IndexPath(row: self.businessArray.count-1, section: 0)], with: UITableViewRowAnimation.automatic)
override func viewDidLoad() {
super.viewDidLoad()
ref = FIRDatabase.database().reference(fromURL:"")
searchController.searchResultsUpdater = self
searchController.dimsBackgroundDuringPresentation = false
definesPresentationContext = true
tableView.tableHeaderView = searchController.searchBar
ref.child("Businesses").queryOrdered(byChild: "Basic-Info/business").observe(.childAdded, with: { (snapshot) in
//insert the rows
self.tableView.insertRows(at: [IndexPath(row: self.businessArray.count-1, section: 0)], with: UITableViewRowAnimation.automatic)
}) { (error) in
print(error.localizedDescription)
}
}
Before inserting the rows in the table view you have to insert the items at the same indexes into the data source array.
However in this case I'd recommend to assign the query result to the data source array and call reloadData()
As #vadian said, you have to modify your datasource to match what you are trying to reflect in the UI. So if we are inserting a row into a UITableView, then you must first insert an object into the datasource at the same index of the row you are adding. Like so:
// First modify datasource
let businessObjectToInsert = BusinessObject() // or whatever your class is
self.businessArray.append(businessObject)
// Then insert row into `UITableView`
self.tableView.insertRows(at: [IndexPath(row: self.businessArray.count-1, section: 0)], with: UITableViewRowAnimation.automatic)

Resources