insertRowsatIndexPath exception iOS - ios

* Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'attempt to insert row 0 into section 0, but there are only 0 rows in section 0 after the update'
I realize the issue here is that I am trying to add a cell to the tableView but it doesn't want it isn't adding one and I can't figure out why.
- (IBAction)addNewIngredient: (id) sender
{
NSString *newIngredient = [recipe createIngredient];
[[recipe ingredients]addObject:newIngredient];
//figure out where that item is in the array
int lastRow = [[recipe ingredients]indexOfObject: newIngredient];
NSIndexPath *ip = [NSIndexPath indexPathForRow:lastRow inSection:0];
NSLog(#"Added a new ingredient!");
[[self tableView] insertRowsAtIndexPaths:[NSArray arrayWithObject:ip] withRowAnimation:
UITableViewRowAnimationTop];
}
To clarify what I'm trying to do here:
recipe has a property ingredients which is an array of NSStrings.
I am adding an object to the ingredients array (does this automatically increase the array count or do I have to do it manually?)...
Then I'm figuring out where that item is in the array with "int lastRow = [[recipe ingredients]indexOfObject:newIngredient]"
Then getting an index path to point there. and then inserting that ingredient into the tableView.

The reason for your exception is that when you insert the row, your numberOfRowsInSection will be called again.
At that time, your data needs to be updated so that if you had 0 rows and are inserting one into it, the function returns 1

Related

tableview refresh crush Thread1:signal SIGABRT

My app is a IM application, when the application into the background and once again back to the foreground will crush.
This is my part of the code。
-(void)uiAddChatroomMessages:(NSArray*)messages{
NSMutableArray *indexPaths = [[NSMutableArray alloc]init];
int i = (short)self.messageArray.count ;
for (RTIMMessage *msg in messages) {
[self.messageArray addObject:msg];
}
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
[indexPaths addObject:indexPath];
[self.chatMessageTableView beginUpdates];
[self.chatMessageTableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade];
[self.chatMessageTableView endUpdates];
[self.chatMessageTableView reloadData];
}
Run to this code "[self.chatMessageTableView endUpdates]",It crush and prompt "Thread1:signal SIGABRT".
2016-08-24 15:49:18.500 RTIM_iOS_Demo[1834:1326398] * Assertion
failure in -[UITableView _endCellAnimationsWithContext:],
/BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit/UIKit-3512.60.12/UITableView.m:1716
2016-08-24 15:49:18.590 RTIM_iOS_Demo[1834:1326398] * 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 (62)
must be equal to the number of rows contained in that section before
the update (57), 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).'
*** First throw call stack: (0x18238adb0 0x1819eff80 0x18238ac80 0x182d10154 0x1876e1808 0x100072ccc 0x1000728b0 0x100095244
0x10009468c 0x100077d20 0x100241a7c 0x100241a3c 0x1002474e4
0x182340d50 0x18233ebb8 0x182268c50 0x183b50088 0x187552088
0x1000a5340 0x181e068b8) libc++abi.dylib: terminating with uncaught
exception of type NSException
In your method you added to self.messageArray some new objects but added just one row. Modify your code to.
-(void)uiAddChatroomMessages:(NSArray*)messages{
NSMutableArray *indexPaths = [NSMutableArray array];
NSUInteger i = self.messageArray.count;
for (RTIMMessage *msg in messages) {
[self.messageArray addObject:msg];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
[indexPaths addObject:indexPath];
i ++;
}
[self.chatMessageTableView beginUpdates];
[self.chatMessageTableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade];
[self.chatMessageTableView endUpdates];
[self.chatMessageTableView reloadData];
}
As per the stack trace it seems like your index path is wrong. You are using array count as row index, try with (array count-1), hope it will work.
After inserting you the number returned by numberOfRowsInSection must match with the new expected value. You might be returning a constant or a number of elements of an array which hasn't changed.

How to pass in section value while storing indexPath in NSMutableArray

I am trying to store indexPath in NSMutableArray
[checkBoxIndexArray addObject:[NSIndexPath indexPathForRow:indexPath.row inSection:?]];
- (void)reloadItemsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths
{
cell.checkBox.image = [UIImage imageNamed:#"check"];
[self.collectionView insertItemsAtIndexPaths:checkBoxIndexArray];
}
but i don't know on what value shall i put for inSection. I tried entering 0,1 but still it's not working. I am getting following 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 (2) must be equal to the number of items contained in that section before the update (2), plus or minus the number of items inserted or deleted from that section (1 inserted, 0 deleted) and plus or minus the number of items moved into or out of that section (0 moved in, 0 moved out).
i am getting this error for following code
[self.collectionView insertItemsAtIndexPaths:checkBoxIndexArray];
Please tell me what value shall i put for inSection.
you should use
[checkBoxIndexArray addObject: indexPath];
NSIndexPath *indexPath=[Your_Table_Name indexPathForSelectedRow];
[checkBoxIndexArray addObject: indexPath];
Doing
[checkBoxIndexArray addObject:[NSIndexPath indexPathForRow:indexPath.row inSection:?]]
is same as doing this
[checkBoxIndexArray addObject:[NSIndexPath indexPathForRow:indexPath.row inSection:indexPath.section]]
OR Doing this
[checkBoxIndexArray addObject:indexPath]
Add the indexPath directly, and later on access the rows or section values as you please.

Why I use indexPathsForSelectedRows to get all cell selected to delete but crashed my app?

Here is some of my code
NSArray *selectedRows = [self.playHistoryTableView indexPathsForSelectedRows];
if (selectedRows.count) {
for (NSIndexPath *selectionIndex in selectedRows)
{
OneSery *sery = [self.playHistoryDic objectAtIndex:selectionIndex.row];
[CoreDataManager deleteOneHistoryBySeryId:sery.seryId andVideoId:sery.latestVideo.videoId];
[self.playHistoryDic removeObjectAtIndex:selectionIndex.row];
}
[self.playHistoryTableView deleteRowsAtIndexPaths:selectedRows withRowAnimation:UITableViewRowAnimationAutomatic];
}
When select the cells one at a time, it works well. But when multiselect the cell it gonna to crash like this:
Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 1 beyond bounds [0 .. 0]'
I know what it mean but I have no idea where I am wrong. And I tried, when it had three cells and I select the first and second to delete, it delete the first and third cell. When it had only two cells, I select both of them to delete, it does crash my app.
When I debug it, even the Onesery *sery value is wrong. So, how could selectionIndex is wrong while selectedRows is right?
Great thanks to #Wain it's finally done with those:
NSArray *selectedRows = [self.playHistoryTableView indexPathsForSelectedRows];
NSMutableIndexSet *indicesOfItemsToDelete = [[NSMutableIndexSet alloc] init];
if (selectedRows.count) {
for (NSIndexPath *selectionIndex in selectedRows)
{
OneSery *sery = [self.playHistoryDic objectAtIndex:selectionIndex.row];
[CoreDataManager deleteOneHistoryBySeryId:sery.seryId andVideoId:sery.latestVideo.videoId];
[indicesOfItemsToDelete addIndex:selectionIndex.row];
}
[self.playHistoryDic removeObjectsAtIndexes:indicesOfItemsToDelete];
[self.playHistoryTableView deleteRowsAtIndexPaths:selectedRows withRowAnimation:UITableViewRowAnimationAutomatic];
}
In your loop you're doing
[self.playHistoryDic removeObjectAtIndex:selectionIndex.row];
so you're changing the list of items. On each iteration you try to access an item, but after the first item the next one has moved, because you removed one. For each subsequent item this is worse.
Eventually you get to a point where you try to access an item but so many have been removed that you go past the end of the list, then you crash.
You should get an array of the items to be removed in your loop and remove them all at once after the loop has completed.

NSInternalInconsistencyException for UITableView when using UICollectionView?

I was trying to insert items into a collection view with this code:
- (IBAction)addCards:(UIButton *)sender {
int numberOfCardsToAdd = EXTRA_CARDS_NUMBER;
if ([[self.collectionView visibleCells] count] == 0) {
numberOfCardsToAdd = self.startingCardCount;}
// loop through the game model, draw random cards from the deck and assign it to the array
// take into account the "no cards left in deck" case
for (int i = 0; i < numberOfCardsToAdd; i++) {
if (![self.game.deck isEmpty]) {
SetsCard *cardToAdd = (SetsCard *) [self.game.deck drawRandomCard];
if (cardToAdd) [self.game.cards addObject:cardToAdd];
NSIndexPath *newObject = [[NSIndexPath alloc] initWithIndex:[self.game.cards indexOfObject:cardToAdd]];
[self.collectionView insertItemsAtIndexPaths:#[newObject]]; // adding card to view
}
}
[self.collectionView reloadData];
}
and I got this error:
Assertion failure in -[NSIndexPath row], /SourceCache/UIKit_Sim/UIKit-2380.17/UITableViewSupport.m:2680
2013-06-13 09:09:12.443 Improved Matchismo[1206:c07] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid index path for use with UITableView. Index paths passed to table view must contain exactly two indices specifying the section and row. Please use the category on NSIndexPath in UITableView.h if possible.'
*** First throw call stack:
(0x1cb1012 0x10eee7e 0x1cb0e78 0xb84665 0x29eb6c 0x54b14d 0x53fd69 0x53e60e 0x53e646 0x926e 0x1102705 0x362c0 0x36258 0xf7021 0xf757f 0xf66e8 0x65cef 0x65f02 0x43d4a 0x35698 0x1c0cdf9 0x1c0cad0 0x1c26bf5 0x1c26962 0x1c57bb6 0x1c56f44 0x1c56e1b 0x1c0b7e3 0x1c0b668 0x32ffc 0x269d 0x25c5)
libc++abi.dylib: terminate called throwing an exception
which really confuses me because I was adding items to an UICollectionView, not an UITableView, and my app does not use any instance of UITableView at all. Does anyone know why I got this error, and how I can fix it?
Thanks very much in advance!
A collection view works with two-level index paths (section/row) in the same way as
a table view, so you should create the index path
NSIndexPath *newObject = [NSIndexPath indexPathForRow:... inSection:0];
if there is only one section (section 0).
-[NSIndexPath row] is declared in the #interface NSIndexPath (UITableView) category and the error message has probably not been changed when collection views were introduced in iOS 6, so the message "Invalid index path for use with UITableView" is misleading.

How to get indexPath.row of tableView which is currently being displayed?

I have a tableView with many values.
I want to get the first indexPath.row value of the table which is being displayed currently.
How can I do that?
I get Following Error while implementing krishnabhadra's answer:
Line at which the error comes is:
[self.table scrollToRowAtIndexPath:indexVis atScrollPosition:UITableViewScrollPositionTop animated:YES];
ERROR:
Assertion failure in -[NSIndexPath row], /SourceCache/UIKit_Sim/UIKit-1447.6.4/UITableViewSupport.m:2018
2011-04-01 11:57:25.458 GlossaryPro[1525:207] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid index path for use with UITableView. Index paths passed to table view must contain exactly two indices specifying the section and row. Please use the category on NSIndexPath in UITableView.h if possible.'
What could be wrong?
You can use tableView indexPathsForVisibleRows function, which returns an NSArray of NSIndexPath for all visible UITableViewCell. From indexPath.row you can find your array index.
NSArray *visible = [tableView indexPathsForVisibleRows];
NSIndexPath *indexpath = (NSIndexPath*)[visible objectAtIndex:0];
indexPath.row will give you index of first object displayed.
[self.myTableView visibleCells];
NSArray *anArrayOfIndexPath = [NSArray arrayWithArray:[self.myTableView indexPathsForVisibleRows]];
NSIndexPath *indexPath= [anArrayOfIndexPath lastObject];
Hope this will help you.
you can use indexPathsForVisibleRows
Returns an array of index paths each identifying a visible row in the receiver.
- (NSArray *)indexPathsForVisibleRows
Return Value
An array of NSIndexPath objects each representing a row index and section index that together identify a visible row in the table view. Returns nil if no rows are visible.
You can use: [self.tableView visibleCells]
That will return a nsarray of UITableViewCell objects, each representing a visible cell in the receiving table view.
http://developer.apple.com/library/ios/#DOCUMENTATION/UIKit/Reference/UITableView_Class/Reference/Reference.html
Get exact index number at center currently being displayed:
let middleIndex = ((tableView.indexPathsForVisibleRows?.first?.row)! + (tableView.indexPathsForVisibleRows?.last?.row)!)/2
Example:
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
let middleIndex = ((tableView.indexPathsForVisibleRows?.first?.row)! + (tableView.indexPathsForVisibleRows?.last?.row)!)/2
print(middleIndex)
}

Resources