InsertRowsAtIndexPaths error Swift - ios

I have an uitableview and i try to append it by insertRowsAtIndexPaths function.
The uitableview appends nicely if i simply add data to the data source arrays, but gives me hard time inserting it by the mentioned above function.
Here is my code
func insertData(){
// appending arrays
answersdict.append(answersmain[answertitle1]![0]) // count 1
resultanswers2d.append(carsmain[answertitle1]!) // count 3
self.tableView.reloadData()
// inserting rows
self.tableView.beginUpdates()
let insertedIndexPathRange = 0..<carsmain[answertitle1]!.count + 1 // total count 4
var insertedIndexPaths = insertedIndexPathRange.map { NSIndexPath(forRow: $0, inSection: 1) }
self.tableView.insertRowsAtIndexPaths(insertedIndexPaths, withRowAnimation: .Fade)
self.tableView.endUpdates()
My datasource count for sections is 2 (so section 1 exists) and for numberOfRows - its equal to resultanswers2d[section].count + 1 which gives me 4
So i'm trying to insert 4 rows into the already appended array that has 4 possible rows in that section, but i'm constantly getting errors like
The number of rows contained in an existing section after the update
(4) must be equal to the number of rows contained in that section
before the update (4), plus or minus inserted cells (4 inserted, 0 deleted)
or if i try to hard
malloc_error
Got stuck. Need any insights. Thank you.

Delete the line to reload the table.
insertRowsAtIndexPaths updates the table accordingly.
The number of insertions and the positions in data source and table must match.

Simply don't call self.tableView.reloadData(). The beginUpdate and endUpdate sections should suffice.
UPDATE:
Also, remember to insert the new section too in the beginUpdate endUpdate block.

Related

UICollection crash Invalid update: invalid number of sections.

The number of sections contained in the collection view after the update (1) must be equal to the number of sections contained in the collection view before the update (1), plus or minus the number of sections inserted or deleted (1 inserted, 0 deleted).
Are you basing your numberOfSections off a model of some sort? What's happening is you're inserting a section into your table view somewhere, reloading your table view data, and then the app is crashing because numberOfSections does not equal The number of sections contained in the collection view after the update.
Without seeing your code it's hard to pinpoint where the problem is, but I would do a look for where you're inserting a section and figure out how to update your numberOfSections accordingly.
A basic example would be having a stored variable like
var sectionsCount = 1
and when you insert a section, you can do sectionsCount = sectionsCount + 1 , reload your tableView data, and have :
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return sectionsCount.count
}
Remember you always have to update your model that you're basing your table view off of BEFORE you reload the data.

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()

NSInternalInconsistencyException occurs when insertng indexPath into tableView but only when row count gets above a certain threshold

I have two tables in which I am dragging and dropping between them: sourceTableView and targetTableView. They each have their own tableViewController. A parentContainerViewController manages a 'slide out' UI which allows the user to 'longPressGesture' on the sourceTableView cell which causes sourceTableView to slide out exposing the targetTableView below at which time the user can 'drop' the dragged cell into place within the targetTableView. All works well as it should until the targetTableView grows to about 21-27 rows in size. Once we get to this size and if I re-run the project I start to get the NSInternalInconsistencyException. The detail of the error reads: reason: 'Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (27) 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).'
At first I thought I was getting a race condition issue since the number of rows before the update is "0" and after it is "27". Maybe the tableView wasn't able to load before the user drags in the item and calls the insertIndex method on tableView. But then I noticed that it works fine until we get to a certain length. Race condition wouldn't make sense in this case. Now I am thinking it has something to do with with 'visible cell' loaded vs not loaded. But why would it be '0' rows? I have looked all over for the answer. There are many NSInconsistency but none that seem to answer my specific problem.
This is the function call to tell targetTableViewController to insert an item into its datasource then tells targetTableView to insertRowsAtIndexPath :
dragDropDataSource.tableView(self, insertDataItem: item, atIndexPath: indexPath)
self.beginUpdates()
self.insertRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Fade)
self.endUpdates()
Here is the targetTableViewController code implementing the above call:
func tableView(tableView: UITableView, insertDataItem dataItem : AnyObject, atIndexPath indexPath: NSIndexPath) -> Void {
if let di = dataItem as? DataItem {
data.insert(di, atIndex: indexPath.row)
}
data is the array that stores the 'DataItems' which are shown in the tableView rows.
Additionally. The targetTableView is initialized with data via a call in its viewDidLoad() to getMyTopTen()
func getMyTopTen() {
let pwAPI = PowWowAPI()
pwAPI.getMyTopTen(self.boardId!) {
(entries:[Entry])in
for(var i=0; i < entries.count; i++) {
let dataItem = DataItem(indexes: String(i), entry: entries[i])
self.data.append(dataItem)
}
}
dispatch_async(dispatch_get_main_queue()) {
self.targetTableView.reloadData()
}
}
I hope I have explained the problem sufficiently. If not please help me make this question better. I am new to asking questions here.

Reload Table view cell with animation (Swift)

Is there a way to reload specific UITableView cells with multiple sections with animations?
I've been using:
self.TheTableView.reloadSections(NSIndexSet(index: 1), withRowAnimation: UITableViewRowAnimation.Right)
This animates all the cells in the section though. The other option is to use:
self.TheTableView.reloadRowsAtIndexPaths(<#indexPaths: [AnyObject]#>,
withRowAnimation: <#UITableViewRowAnimation#>)
EDIT:
After using reloadRowsAtIndexPaths
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 (5) must be equal to the number of rows contained in that section before the update (4), 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).'
Trying to find a smooth way of reloading a tableview by appending objects into an array.
Calling TheTableView.reloadData() before reloadRowsAtIndexPaths works, but the animation is glitchy. Is there another approach?
Why not just reload the cells directly? The indexPath contains the section and row so just keep track of which section you want to reload and fill the indexes in that array.
var indexPath1 = NSIndexPath(forRow: 1, inSection: 1)
var indexPath2 = NSIndexPath(forRow: 1, inSection: 2)
self.tableView.reloadRowsAtIndexPaths([indexPath1, indexPath2], withRowAnimation: UITableViewRowAnimation.Automatic)
Based on your comment you are looking to change your array and have the tableView animate in the changes. If that's the case you should consider using beginUpdates() and endUpdates() for UITableViews or even an NSFetchedResultsController so it handles all of the update animations cleanly.
self.tableView.beginUpdates()
// Insert or delete rows
self.tableView.endUpdates()
I'd recommend using NSFetchedResultsController if you're using Core Data as it simplifies this entire process. Otherwise you have to handle the changes yourself. In other words, if your array changes you need to manually remove or insert rows in the tableview using beginUpdates() and endUpdates().
If you aren't using Core Data, study this to grasp how it's all handled.
In Swift 3.0
We can reload particular row of particular section in tableview
let indexPath = IndexPath(item: 2, section: 0)
self.tableView.reloadRows(at: [indexPath], with: .automatic)
If you want to reload single section in swift 3.0 you can do this:
tableView.reloadSections(IndexSet(integer: 0), with: .automatic)
the define IndexSet in official document:
Manages a Set of integer values, which are commonly used as an index
type in Cocoa API. The range of valid integer values is
in (0, INT_MAX-1). Anything outside this range is an error.
so IndexSet is Set about index, just putting some Int values in [ ]
// for reload one section
tableView.reloadSections([section], with: .automatic)
// or using like this
tableView.reloadSections(IndexSet(integer: section), with: .automatic)
// for reload multi sections
tableView.reloadSections([1, 2, 3, section], with: .automatic)

NSInternalInconsistencyException when removing rows from a UITableView

I'm receiving an error indicating that I need to update the number of rows in my UITableView after I have deleted a row. I realise that It's because I've not updated the amount of rows in the UITableView, I'm just not sure how to make this change in the code I have below.
Any assistance is really appreciated.
!-- code
NSIndexPath[] rowsToReload = new NSIndexPath[] {
NSIndexPath.FromRowSection(1, 1)
};
dv.TableView.BeginUpdates ();
dv.TableView.DeleteRows(rowsToReload,UITableViewRowAnimation.Automatic);
dv.TableView.EndUpdates ();
!-- error
Name: NSInternalInconsistencyException Reason: Invalid update: invalid number of rows in section 1. 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 (3)
Your code above is OK. However, you need to call it after you have removed the corresponding items from your data source.
For example, if you are filling your table view from a List<string> (myList) and you wanted to remove the first row:
myList.RemoveAt(0); // remove the item from the list first
NSIndexPath[] rowsToDelete = new NSIndexPath[] {
NSIndexPath.FromRowSection(0, 0)
};
dv.TableView.DeleteRows(rowsToDelete, UITableViewRowAnimation.Automatic);
No need to wrap the DeleteRows call in a Begin/EndUpdates, as you only have one delete action to perform. That is used when you have multiple different actions (eg. DeleteRows + InsertRows) so that the animations are performed smoothly.
#Dimitris thanks for answering my question. I ended up solving the problem by:
calling the reload method on my UITableView
NSIndexPath[] rowsToReload = new NSIndexPath[] {
NSIndexPath.FromRowSection(1, 1)
};
dv.TableView.ReloadRows (rowsToReload,UITableViewRowAnimation.None);
in my UITableViewCell GetCell method
I removed the label, field and button that were included on the first load of the table. Since this screen in my app will be seen only once, when the user loads it for the first time.

Resources