Swift 3 range exception? - uitableview

let x = self.tableProduct.count
self.tableProduct = products
self.tableView.beginUpdates()
var insertedIndexPaths = [IndexPath]()
for i in x..<self.tableProduct.count {
print("No : \(i)")
insertedIndexPaths.append(IndexPath(row: i, section: 0))
}
print("Count = \(self.tableProduct.count)")
print(insertedIndexPaths)
self.tableView.insertRows(at: insertedIndexPaths, with: .none)
self.tableView.endUpdates()
Here x is the current array count. Since I'm fetching in background after assigning I update array in second line. Then I start updating table view. Lets say initially my table has 50 records that is x, then I want to add row from 51 to self.tableProduct.count which is 100. In for loop I add index path my first index path is [0,51] and last index path looks like [0,99]. Then I start to insert my new rows, here it throws
Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 17 beyond bounds [0 .. 16]'
error.When I add breakpoint to error it shows error in tableView.endUpdates() line.Here what I'm doing wrong? How can I solve this error? Thanks in advance.

Related

'NSRangeException', reason: '*** -[__NSArrayM objectAtIndexedSubscript:]: index 1 beyond bounds [0 .. 0]'

I've added exception breakpoints and it always blows up on this line
BookPage *page = _sections[path.section].pages[path.row];
Bare in mind I'm new in objective-c
Any help would be appreciated.
In this code have two places where this Exception one is _sections[path.section] and another is the full code.
First check the _sections contains the pages array of that position path.section. If contains then check count the pages count and then try to get the row value.
Like this:
if ([_sections count] > path.section){
if ([_sections[path.section].pages count] > path.row){
BookPage *page = _sections[path.section].pages[path.row];
}
}
Hope this will fix your problem.

Invalid update: invalid number of sections

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of sections. The number of sections contained in the table view after the update (3) must be equal to the number of sections contained in the table view before the update (3), plus or minus the number of sections inserted or deleted (1 inserted, 0 deleted).'
but i insert 1 and deleted one based on data source what i missed
self.states?.append(sortedStates) //Update state property
if (self.states?.count)! > 3 {
self.states?.removeFirst()
}
self.newsFeedTableView.beginUpdates()
self.newsFeedTableView.insertSections([(self.states?.count)! - 1], with: .none)
if (self.states?.count)! > 3 {
let statesForoldestStateTime = self.states?.first
self.newestStateTime = statesForoldestStateTime?.first?.createdAt
let indexpostion = (self.states?.count)! - 3
self.newsFeedTableView.deleteSections([indexpostion], with: UITableViewRowAnimation.none)
}
self.newsFeedTableView.endUpdates()
The error says it all. When if (self.states?.count)! > 3 is false. The only section would be inserted and not deleted.
You should update your data source accordingly. The number of sections method must return someArray.count. When you insert some section, make sure to update that some array, and when you delete some section, delete the element from some array. That will resolve the issue.

Seemingly random indexes causes out of bounds error when referencing a cell in a table view

I'm not sure if I'm missing something very basic or if this is just another problem I've run into with Swift UITableviews. My problem is that I reference a cell in the table view (in this case section 4 row 0) and for some reason swift is giving me an out of bounds error with an index (6) that shouldn't ever exists because the size of the section should only be 4 the log also never showed a 5 (when printing positionCounter in the while loop). Any help would be greatly appreciated I have no idea why I would be getting a value of 6 in this instance please let me know if you need me to provide any extra code or clarify anything.
Error Message
*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 6 beyond bounds [0 .. 5]'
The code surrounding the error
cell = tableView.dequeueReusableCell(withIdentifier: "Item Card", for: indexPath)
var positionCounter = 0
while positionCounter < eventSettingsTableView.numberOfRows(inSection: 4) {
print(positionCounter)
print(String(eventSettingsTableView.numberOfSections) + " NUMBER OF SECTIONS")
print(String(eventSettingsTableView.numberOfRows(inSection: 4)) + " NUMBER OF ROW IN SECTION 4")
if eventSettingsTableView.cellForRow(at: IndexPath(row: 0, section: 4)) != nil {
print("no")
} else {
print("yes")
}
positionCounter = positionCounter + 1
}
positionCounter = 0
I have narrowed the error down to this line (changing the section from 4 to 3 fixes the error but doesn't explain why positionCounter was ever 6)
if eventSettingsTableView.cellForRow(at: IndexPath(row: 0, section: 4)) != nil {
EDIT - Sorry forgot to mention that this code is located in the cellForRowAt function for my UITableView
It appears that you are calling cellForRowAt: from within cellForRowAt:. This is going to cause issues depending on the situation. You might want to look at implementing the following logic differently:
if eventSettingsTableView.cellForRow(at: IndexPath(row: 0, section: 4)) != nil {
print("no")
} else {
print("yes")
}
Update:
As #PaulW11 points out, calling the tableview's cellForRowAt: from within the data source cellForRowAt: should not be an issue. And he's right.
However, I set up a demo project to investigate the issue and removing the call to cellForRowAt: but retaining the loop results in the crash not occurring. Additionally, I set up a static array of data and noticed that the crash was not due to a boundary condition either since while the array was 9 items long, I got out of bounds issues indicating that iOS was looking at a 12 item array where the access seemed to be for the 13th item :)
So, at the moment, my suspicion is that this issue is due to some sort of timing/race condition where cellForRowAt: is called multiple times within a loop and something goes wonky. But what that "something" is, I don't know. If somebody has any ideas, I'd be really interested to hear about it since this is an interesting question ...

inserting a fake row#indexPath, iOS

Im creating a new table, and within it, Im inserting a new row with fake text, but I get the crash report
Terminating app due to uncaught exception
'NSInternalInconsistencyException', reason: 'attempt to insert row 5
into section 0, but there are only 5 rows in section 0 after the
update
after some fiddling around, I changed my code from:
#IBAction func add() {
let newRow = ChecklistItems(text: "Im the new Row", checked: false)
items.append(newRow)
let index = items.count
let indexPath = NSIndexPath(forRow: index, inSection: 0)
tableView.insertRowsAtIndexPaths([indexPath], withRowAnimation: .Left)
}
TO THIS:
#IBAction func add() {
let index = items.count
let newRow = ChecklistItems(text: "Im the new Row", checked: false)
items.append(newRow)
let indexPath = NSIndexPath(forRow: index, inSection: 0)
tableView.insertRowsAtIndexPaths([indexPath], withRowAnimation: .Left)
}
can someone explain to me the actual details why this switch made the code work?
thank you so much~
Welcome to SO.
In your first version, you add an item to your items array, then create an indexPath which points to the count of the array (So if the array contains 5 items, you create an indexPath value of row:5, section:0)
However, arrays are zero-based. If an array contains 5 elements, valid array indexes are 0 - 4. The same goes for indexPath values. The highest valid row value is totalRows - 1. If the array contains 5 elements, 5 is not a valid array index.
In the second version of your code, index = the item count BEFORE adding an item. So if the row contains 4 items, count = 4, you add an item, and now items contains 5 items and 4 is a valid index into the array, so the insert does not refer to an item that's beyond the end of your items array.
Because the indexPath is beginning with 0, so it's max value is the items.count - 1
Because count is starting from 1, but NSIndexPath and also array index starting from 0.
so lets say you have an array of ("a", "b", "c"), array count is 3. but the index of it is 0, 1, 2.
so with your first code, you add new item and choose the index based on its count which is beyond its array index. for example you add new item "d" to example array above, the count will be changed to 4. But the max index is 3, which is why it throws error.
with your second code, you get the index based on count first before adding. So you set index for item d with 3, because the array only contain a, b, c and then add d to array.
it is working for you right now, but it will potentially create a mismatch between your array index and your tableView index.
A good way to retrieve object index is using array function indexOf.

NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 5 beyond bounds for empty array'

in my application when i run app for first time,it work ok.but when i run again 2 two times, it crashes.
This is the error..
NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 5 beyond bounds for empty array'
Reason: You are accessing Empty array about to access object at index.
replace all places like in your code below
[arrMydata objectAtIndex:indexPath.row];
with
//1. Positive index ([anArray objectAtIndex:-NUMBERS]) will crash
//2. within the array boundary
if([arrMydata count] > 0 && [arrMydata count] > indexPath.row){
shrObj=[arrMydata objectAtIndex:indexPath.row];
}
else{
//Array is empty,handle as you needed
}
**Here You can see the non software example, which will explain this issue. Good luck! **
You array is empty, but you're trying to access an object in it. That is the problem.
Reason: According to your log, you're trying to access empty array. Just fix this by below code
if (arrMydata.count > inxexPath.row)
sharObj = [arrMydata objectAtIndex:indexPath.row]
In case this helps someone : in my case the array was not in code, but an IB outlet that was an array of 5 UIImageViews in the storyboard.
#IBOutlet var upAndDownArrowImages: [UIImageView]!
Reason for the crash was that I mistakenly deleted 1 of those UIImageViews from the Storyboard.
In my case, it Crashes for heightForRowAt indexpath, Do check this method for smooth operation.
Hope it Helps someone.

Resources